跳至主要内容

DISTINCT 子句

如果指定了 SELECT DISTINCT,则查询结果中将只保留唯一行。因此,在结果中所有完全匹配的行集中,将只保留一行。

您可以指定必须具有唯一值的列列表:SELECT DISTINCT ON (column1, column2,...)。如果未指定列,则将考虑所有列。

考虑以下表格

┌─a─┬─b─┬─c─┐
│ 1 │ 1 │ 1 │
│ 1 │ 1 │ 1 │
│ 2 │ 2 │ 2 │
│ 2 │ 2 │ 2 │
│ 1 │ 1 │ 2 │
│ 1 │ 2 │ 2 │
└───┴───┴───┘

使用 DISTINCT 而不指定列

SELECT DISTINCT * FROM t1;
┌─a─┬─b─┬─c─┐
│ 1 │ 1 │ 1 │
│ 2 │ 2 │ 2 │
│ 1 │ 1 │ 2 │
│ 1 │ 2 │ 2 │
└───┴───┴───┘

使用 DISTINCT 并指定列

SELECT DISTINCT ON (a,b) * FROM t1;
┌─a─┬─b─┬─c─┐
│ 1 │ 1 │ 1 │
│ 2 │ 2 │ 2 │
│ 1 │ 2 │ 2 │
└───┴───┴───┘

DISTINCT 和 ORDER BY

ClickHouse 支持在一个查询中对不同列使用 DISTINCTORDER BY 子句。DISTINCT 子句在 ORDER BY 子句之前执行。

考虑以下表格

┌─a─┬─b─┐
│ 2 │ 1 │
│ 1 │ 2 │
│ 3 │ 3 │
│ 2 │ 4 │
└───┴───┘

选择数据

SELECT DISTINCT a FROM t1 ORDER BY b ASC;
┌─a─┐
│ 2 │
│ 1 │
│ 3 │
└───┘

使用不同的排序方向选择数据

SELECT DISTINCT a FROM t1 ORDER BY b DESC;
┌─a─┐
│ 3 │
│ 1 │
│ 2 │
└───┘

2, 4 在排序前被裁剪。

在编写查询时请考虑此实现特性。

空值处理

DISTINCT 处理 NULL 的方式就像 NULL 是一个特定值,并且 NULL==NULL。换句话说,在 DISTINCT 结果中,不同的 NULL 组合只出现一次。这与大多数其他上下文中的 NULL 处理方式不同。

替代方案

可以通过对与 SELECT 子句中指定的相同值集应用 GROUP BY 来获得相同的结果,而无需使用任何聚合函数。但是与 GROUP BY 方法有一些区别

  • DISTINCT 可以与 GROUP BY 一起使用。
  • 当省略 ORDER BY 并定义 LIMIT 时,查询将在读取所需数量的不同行后立即停止运行。
  • 数据块在处理时输出,而无需等待整个查询完成运行。