SELECT用于从一个表或者多个表中查询数据。本文为您介绍SELECT的基本语法以及部分子句。
基本语法
在SELECT语句的语法中,除了表达式列表(expr_list),其他子句均为可选。更多信息,请参见 查询语法 。
语法
SELECT [DISTINCT] expr_list
[FROM [db.]table | (subquery) | table_function] [FINAL]
[SAMPLE sample_coeff]
[ARRAY JOIN ...]
[GLOBAL] ANY|ALL INNER|LEFT JOIN (subquery)|table USING columns_list
[PREWHERE expr]
[WHERE expr]
[GROUP BY expr_list] [WITH TOTALS]
[HAVING expr]
[ORDER BY expr_list]
[LIMIT [n, ]m]
[UNION ALL ...]
[INTO OUTFILE filename]
[FORMAT format]
[LIMIT n BY columns]
示例
SELECT
OriginCityName,
DestCityName,
count(*) AS flights,
bar(flights, 0, 20000, 40)
FROM ontime_distributed
WHERE Year = 1988
GROUP BY OriginCityName, DestCityName
ORDER BY flights DESC
LIMIT 20;
SAMPLE子句
SAMPLE子句的作用是近似查询。
SAMPLE子句仅适用于
*MergeTree
类型的表且建表时已指定采样表达式。
SAMPLE子句可以使用
SAMPLE k
来表示,其中k可以是比例,也可以是一个具体的数值。
-
k为比例时:
-
k取值:
0<k<1
。 -
查询将使用'k'作为百分比选取数据。例如,
SAMPLE 0.1
查询只会检索数据总量的10%。 -
可用于统计所有数据的近似值。计算公式:统计使用SAMPLE子句的结果的个数/k。
-
-
k为具体数值时:
-
查询将使用'k'作为最大样本数。例如,
SAMPLE 10000000
查询只会检索最多10,000,000行数据。 -
无法用于统计所有数据近似值。
-
示例
以下为仅查询10%数据的示例。
count()
的结果只是10%数据量的计数结果,想要统计所有数据的计数结果,需要将
count()
的结果手动乘以10,才能得到近似查询的结果。
SELECT
Title,
count() * 10 AS PageViews
FROM hits_distributed
SAMPLE 0.1
WHERE
CounterID = 34
AND toDate(EventDate) >= toDate('2013-01-29')
AND toDate(EventDate) <= toDate('2013-02-04')
AND NOT DontCountHits
AND NOT Refresh
AND Title != ''
GROUP BY Title
ORDER BY PageViews DESC LIMIT 1000;
ARRAY JOIN子句
ARRAY JOIN
子句作用是与数组类型或Nested数据类型的字段进行JOIN操作。其作用与arrayJoin函数相似,但功能更广泛,使用更灵活。
-
与数组类型JOIN:将一行中的数组字段展开为多行,每行包含数组中的一个元素,这样就可以针对数组每个元素执行进一步的查询或聚合操作。
-
与Nested类型JOIN:对于Nested类型的列,
ARRAY JOIN
不仅会展开数组,还会保持数组内部元素的结构关系,使得可以针对嵌套字段进行查询。
示例
-
创建测试表arrays_test。
CREATE TABLE arrays_test
s String,
arr Array(UInt8)
) ENGINE = Memory
-
插入测试数据。
INSERT INTO arrays_test VALUES ('Hello', [1,2]), ('World', [3,4,5]), ('Goodbye', [])
-
查询表arrays_test。
SELECT * FROM arrays_test;
结果集:
┌─s───────┬─arr─────┐
│ Hello │ [1,2] │
│ World │ [3,4,5] │
│ Goodbye │ [] │
└─────────┴─────────┘
-
使用ARRAY JOIN子句查询表arrays_test。
SELECT s, arr FROM arrays_test ARRAY JOIN arr;
结果集:
┌─s─────┬─arr─┐
│ Hello │ 1 │
│ Hello │ 2 │
│ World │ 3 │
│ World │ 4 │
│ World │ 5 │
└───────┴─────┘
JOIN语句Null的处理
JOIN语句中的Null处理,请参见 join_use_nulls 、 Nullable 、 Null 。
WHERE子句
WHERE子句用过滤数据。
-
WHERE子句必须包含一个UInt8类型的表达式,该表达式通常是条件表达式。
-
在支持索引的表中,WHERE子句决定了查询语句是否使用索引。
PREWHERE子句
PREWHERE子句与WHERE子句作用相似,用于查询过滤数据。更多详情,请参见 PREWHERE 。
-
PREWHERE仅支持*MergeTree系列引擎。
-
在一个查询中可以同时指定PREWHERE和WHERE,在这种情况下,PREWHERE优先于WHERE执行。
-
PREWHERE不适合用于已经存在于索引中的列,因为当列已经存在于索引中的情况下,只有满足索引的数据块才会被读取。
-
如果将'optimize_move_to_prewhere'设置为1,并且在查询中不包含PREWHERE,则系统将自动的把适合PREWHERE表达式的部分从WHERE中抽离到PREWHERE中。
使用场景
过滤条件中有少量不适合索引过滤的列,但是这些过滤条件又有较强的过滤能力,此时可以使用PREWHERE,减少读取的数据量。例如,在一个查询中有很多列时,在PREWHERE子句中对少量列进行过滤。
WITH TOTALS修饰符
如果
GROUP BY
子句指定了
WITH TOTALS
修饰符,返回结果将多出一行。
-
该行包含所有关键列的默认值(零或者空值),以及所有行的聚合结果。
-
该行仅在JSON*、TabSeparated*、Pretty*输出格式中与其他行分开输出。
示例
-
创建测试表t1。
CREATE TABLE default.t1
`a` Int32,
`b` Int32,
`c` String,
`d` Date
ENGINE = MergeTree
PARTITION BY toYYYYMM(d)
ORDER BY (a, b)
SETTINGS index_granularity = 8192;
-
插入测试数据。
INSERT INTO t3(a, b, c, d) INSERT INTO t1(a, b, c, d) VALUES (3,4,'a','2022-09-01'),(12,7,'b','2022-07-01'),(21,4,'c','2022-05-01'),(11,1,'d','2022-06-01');
-
查询表t1中的数据,按列d进行分组,并返回列a分组汇总的结果。
select sum(a) from t1 group by d;
结果集:
┌─sum(a)─┐
│ 21 │
│ 11 │
│ 12 │
│ 3 │
└────────┘
-
使用
WITH TOTALS
修饰符查询表t1中的数据,按列d进行分组,并返回列a分组汇总的结果。
select sum(a) from t1 group by d with totals;
结果集:
┌─sum(a)─┐
│ 21 │
│ 11 │
│ 12 │
│ 3 │
└────────┘
Totals:
┌─sum(a)─┐
│ 47 │
└────────┘