可含任意多个分组字段表达式列表,与limit无关系,limit n by columns可用在每个columns分组中求最大的n行数据
为每个domain, device_type的组合选出前5个访问最多的数据,但是结果最多将不超过100行(LIMIT n BY + LIMIT)
SELECT
domainWithoutWWW(URL) AS domain,
domainWithoutWWW(REFERRER_URL) AS referrer,
device_type,
count() cnt
FROM hits
GROUP BY domain, referrer, device_type
ORDER BY cnt DESC
LIMIT 5 BY domain, device_type
LIMIT 100
过滤group by后是数据,类似where;where在聚合前执行,having聚合后执行,不存在聚合不能使用having
如存在order by,则该子句中须存在一个表达式列表,列表中每个表达式都可分配desc或asc,默认asc
1、字符串在指定排序规则时,不区分大小写
2、排序中相同值的行以任意顺序输出;省略order by,结果的顺序也是不固定的
3、collate效率低于正常排序,少量使用
NaN和NULL:
使用nulls first,先输出null,然后nan,最后其他值
使用nulls last,先输出其他值,nan,null(默认)
SELECT * FROM t_null_nan ORDER BY y NULLS FIRST:
┌─x─┬────y─┐
│ 1 │ ᴺᵁᴸᴸ │
│ 7 │ ᴺᵁᴸᴸ │
│ 1 │ nan │
│ 6 │ nan │
│ 2 │ 2 │
│ 2 │ 2 │
│ 3 │ 4 │
│ 5 │ 6 │
│ 6 │ 7 │
│ 8 │ 9 │
4、浮点类型,nan总出现all后面
5、order by子句后limit较小数值,将使用较少内存,否则内存使用量将于需排序的数据成正比
分布式查询:省略了group by,在远程服务器上执行部分排序,最后再请求服务器上合并排序结果,排序数据量可以大于单台服务器内存
6、无足够内存,可使用外部排序(磁盘建临时文件,效率低)max_bytes_before_external_sort设置外部排序,=0禁用、启用该功能,要排序的数据量达到所指定的字节数时 当前排序结果被转存到临时文件中,全部数据读取完毕后,所有临时文件被合并成最后结果,临时文件在config文件配置的/var/lib/clickhouse/tmp/目录中,修改tmp_path调整
7、查询运行使用的内存要高于max_bytes_before_external_sort,为此这个配置须远小于max_memory_usage配置的值
存在聚合函数:对聚合函数之前的表达式进行分析
聚合函数与聚合函数前的表达式都将在聚合期间完成计算
完全相同的行去重,在GROUP BY不包含聚合函数,并对全部SELECT部分都包含在GROUP BY中时的作用一样??
select表达式中存在array类型的列时,不能使用distinct
distinct可与null一起工作,与null不同组合仅能出现一次
limit m结果中选择前m行数据,limit n,m查找结果中选择n-m行数据
未指定order by,结果可能任意的顺序,且不确定
ELECT CounterID, 1 AS table, toInt64(count()) AS c
FROM test.hits
GROUP BY CounterID
UNION ALL
SELECT CounterID, 2 AS table, sum(Sign) AS c
FROM test.visits
GROUP BY CounterID
HAVING c > 0
1、仅支持union all,如需union distinct,可使用union all中包含select distinct的子查询方式
2、union all中查询可同时运行,他们的结果混合在一起
3、查询结果:列数量和类型须相同,列名可不同:最终的列名将从第一个查询获取,union会为查询间进行类型转换
4、union all查询的部分不能包含在括号内,order by与limit子句应该被应用在每个查询中,如需要做最终结果转换,可将union all作为子查询含在from子句中
将查询结果重定向输出到指定文件中,与mysql不同,执行结果将在客户端建立,如文件存在则查询将失败,工作在命令行客户端与clickhouse-local中,默认输出格式是tabseparated
指定返回数据的格式,可使用它方便的转换或创建数据的转储
不存在format子句,使用默认格式:取决与DB配置及所使用的客户端
批量模式的http客户端和命令行,默认格式tabseparated;交互模式下命令行客户端,默认格式是prettycompact
使用命令行,数据以内部高效的格式在服务器与客户端间传递,客户端将单独解析format,助格式转换
对应in 、not in、global in global not in操作符被分别实现,
SELECT UserID IN (123, 456) FROM ...
SELECT (CounterID, UserID) IN ((34, 123), (101500, 456)) FROM ...
如左侧是单列且是一个索引,且右是一组常量时,系统使用索引来处理查询
不用在列表列太多值,数据集很大,将他们放入临时表,再使用子查询
SELECT
EventDate,
avg(UserID IN
(
SELECT UserID
FROM test.hits
WHERE EventDate = toDate('2014-03-17')
)) AS ratio
FROM test.hits
GROUP BY EventDate
ORDER BY EventDate ASC
in操作符总是假定null值的操作结果=0,null值不应该被包含在数据集中:彼此不对应、不能比较
┌─x─┬────y─┐ │ 1 │ ᴺᵁᴸᴸ │ │ 2 │ 3 │ └───┴──────┘ |
┌─x─┐ │ 2 │ └───┘ |
SELECT x FROM t_null WHERE y IN (NULL,3) | 不确定null是否包含在(null,3)返回0,结果集中排除该行 |
带有子查询的in
1、普通in,查询发送到远程服务器,且每个服务器中运行in或join子句的子查询
2、global in、global join时,先为global in、global join运行所有子查询,将结果收到临时表且将表发给每个服务器,使用临时表运行查询
非分布式查询,使用普通的in、join
假设集群中每个服务器都存在一个正常表local_table,与分布式表distributed_table
对distributed_table查询,查询被送到服务器且使用local_table运行查询
SELECT uniq(UserID) FROM distributed_table
发送如下查询到服务器
SELECT uniq(UserID) FROM local_table
并行执行,直到达到可组合数据的中间结果状态,然后中间结果将返回到服务器且在合并,最终将结果发送给客户端
2、SELECT uniq(UserID) FROM distributed_table WHERE CounterID = 101500 AND UserID IN (SELECT UserID FROM local_table WHERE CounterID = 34)
SELECT uniq(UserID) FROM local_table WHERE CounterID = 101500 AND UserID IN (SELECT UserID FROM local_table WHERE CounterID = 34)
in子句中的数据集将被每台服务器独立收集,仅与每台服务器上的本地存储上的数据计算交集,未将数据分散到每台服务器上,结果不准确
改为:
SELECT uniq(UserID) FROM distributed_table WHERE CounterID = 101500 AND UserID IN (SELECT UserID FROM distributed_table WHERE CounterID = 34)
SELECT uniq(UserID) FROM local_table WHERE CounterID = 101500 AND UserID IN (SELECT UserID FROM distributed_table WHERE CounterID = 34)
子查询将在每台服务器上执行,因为子查询是分布式表,so每个服务器上的子查询将查询再次发送给所有的远程服务器
SELECT UserID FROM local_table WHERE CounterID = 34
台多,使用global
SELECT uniq(UserID) FROM distributed_table WHERE CounterID = 101500 AND UserID GLOBAL IN (SELECT UserID FROM distributed_table WHERE CounterID = 34)
服务器上运行子查询:
SELECT UserID FROM distributed_table WHERE CounterID = 34
将结果放入内存中临时表中,然后将请求发送到每个服务器(临时表也随着一起发送)
SELECT uniq(UserID) FROM local_table WHERE CounterID = 101500 AND UserID GLOBAL IN _data1
注意:
1、创建临时表,在子查询中使用distinct
2、临时表将发送到服务器,传输不考虑网络拓扑结构
3、向服务器发送数据,网络带宽限制不可配置,对网络负载造成压力
4、尝试将数据跨服务器分布,将不需要用global in
5、如经常使用global all,请规划你的clickhouse集群位置,以便副本间不跨数据中心,且具有快速网络交换能力:查询可完全在一个数据中心完成
将extremes=1,获得结果列最值(数字、日期类型进行计算,其他类型输出默认值)
额外计算的最值:两行数据仅在JSON*, TabSeparated*, and Pretty* 格式与其他行分开出输出,不支持其他输出格式
json*格式,extreme值在单独的extremes中
在tabseparated*格式,在其他结果与totals后输出,且使用空行与其分隔
在pretty*中,与其他结果与totals后以单独表格输出
在计算extreme值同时使用了limit,extreme计算结果将含offset跳过的行
流式请求中,可能还含多余limit的少量行的值
group by与order by不支持使用列位置信息作为参数,group by 1,2 ==按照常量进行分组:all行聚合成一行
可在查询的任何部分使用AS
任何部分添加*(不仅仅是表达式),分析查询时*被替换为all的列(不含materialized 与 alias列)
不推荐使用,如下可以使用:合理
创建表存储时、对于仅包含几个列的表、获取表中韩列信息(应用limit 1 更好的是desc table)
使用prewhere在少数几个列上做强过滤、子查询中(外部查询不需要的列被排除在子查询外)
https://clickhouse.yandex/docs/zh/query_language/select/