如果指定了 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 支持在一个查询中对不同列使用 DISTINCT 和 ORDER 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 被截断。
在编写查询时,请考虑此实现特性。
Null 处理
DISTINCT 将 NULL 视为特定值进行处理,并且 NULL==NULL。换句话说,在 DISTINCT 的结果中,带有 NULL 的不同组合仅出现一次。这与大多数其他上下文中的 NULL 处理有所不同。
替代方案
可以通过在与 SELECT 子句中指定的相同值集上应用 GROUP BY 来获得相同的结果,而不使用任何聚合函数。但与 GROUP BY 方法有一些不同之处:
DISTINCT 可以与 GROUP BY 一起使用。
- 当省略 ORDER BY 且定义了 LIMIT 时,查询在读取到所需数量的不同行后会立即停止运行。
- 数据块在处理时输出,而无需等待整个查询完成运行。