【clickhouse SQL语句03】
数组去重、拼接、排序、增删
一、去重 1.arrayDistinct 对数组进行去重 SELECT arrayDistinct( [1,2,3,6,34,3,11]) 2.arrayUniq 计算数组中有多少个不重复的值 SELECT arrayUniq( [1,2,3,6,34,3,11]) 3.arrayCompact 对数组内数据实现相邻去重 SELECT arrayCompact([1, 2, 2, 3, 2, 3, 3]) 二、数组属性 1.arrayJoin 对数组进行展开操作,行变列 SELECT arrayJoin( [1,2,3,6,34,3,11] ) as a 2.arrayFilter 筛选出数组中满足条件的数据 SELECT a from (SELECT arrayFilter(x->x%2=0, [1,2,3,6,34,3,11]) as a 3.arrayEnumerate 返回数组下标 SELECT arrayEnumerate([1,2,3,6,34,3,11]) 4.arrayReduce 对数组进行聚合操作,如有min 、max、avg 等 SELECT arrayReduce('avg', [1,2,3,6,34,3,11] ) 5.arrayEnumerateDense 标记出数组中相同的元素 SELECT arrayEnumerateDense( [1,2,3,6,34,3,11] ) 6.hasAny 判断数组中是否包含某些值中任意一个值,若包含则返回1,否则返回0 SELECT hasAny( [1,2,3,6,34,3,11] , [3,4]) 7.hasAll 判断数组中是否包含某些值中所有值,若包含则返回1,否则返回0 SELECT hasAll( [1,2,3,6,34,3,11] , [3,4]) 8.arrayWithConstant 生成一个指定长度的数组 SELECT arrayWithConstant( 3, 'a') 三、切割/拼接 1.arrayStringConcat 将数组元素按照给定分隔符进行拼接,返回拼接后的字符串(数组元素必须为String类型) SELECT arrayStringConcat( ['2020','12','19'], '-') 2.arraySlice 对数组进行切割 ,后面两个参数分别是切割的位置和切割后的段数 SELECT arraySlice( [1,2,3,6,34,3,11],-3,2) 四、排序 1.arraySort 对数组进行升序 SELECT a from (SELECT arraySort([1,2,3,6,34,3,11]) as a) 2.arrayReverseSort 对数组进行降序 SELECT a from (SELECT arrayReverseSort([1,2,3,6,34,3,11]) as a) 五、添加/删除首尾元素 1.arrayPushFront 在数组首位添加元素 SELECT arrayPushFront( [1,2,3,6,34,3,11] , 8) 2.arrayPushBack 在数组末尾添加元素 SELECT arrayPushBack( [1,2,3,6,34,3,11] , 8) 3.arrayPopFront 删除数组中第一个元素 SELECT arrayPopFront( [1,2,3,6,34,3,11] ) 4.arrayPopBack 删除数组中最后一个元素 SELECT arrayPopBack( [1,2,3,6,34,3,11] ) 六、计算差值 1.arrayDifference 计算数组中前后两个值的差值部分,该位=当前-前者(不包括第一个数,结果第一位默认为0) SELECT arrayDifference( [1,2,3,6,34,3,11] ) 2.runningDifference 计算某一列前后数值的差值,该位=当前-前者(不包括第一个数,结果第一位默认为0) select a,runningDifference(a) from (SELECT arrayJoin( [1,2,3,6,34,3,11]) as a)
1、with
#语法
with 表达式 as name
select x from xxx
with语法有三种形式:
- 定义变量
- 调用函数
- 查询
形式1:定义变量 -->注意:这种是要给字段赋一个临时的值,所以select的时候必须查这个字段,如果查*输出的结果仍然是原数据的值
with 'hello' as sku_id
select sku_id,* from t_order_mt
形式2:调用函数
with toYYYYMM(create_time) as dy
select dy,* from t_order_mt limit 2;
-- 语句解析:用with调用函数toYYYYMM把create_time定义成年月
实际工作中真实的sql
WITH
JSONExtract( data, 'event_raw_log', 'JSON') AS event_raw_log
,JSONExtract( event_raw_log, 'device_info', 'JSON') AS device_info
,JSONExtractString(device_info,'device_id') as device_id
SELECT device_id,* FROM target_event_attribution
where device_id = 'b6d17958-06f5-4fc5-9097-d4b79a3dfb51' and appkey = '750bb7f034cd701b'
ORDER BY db_time desc
limit 10 ;
形式3:执行查询 --->返回结果必须是一行,否则就报错
语法:with () as xx
1)全局聚合 sum count avg
with (select count(1) from t_order_mt) as cnt
select cnt,* from t_order_mt limit 2;
2、array join 函数获取每一行并将他们展开到多行(unfold)
- 获取数组的角标
SELECT
id,
name,
bobby,
arrayEnumerate(bobby) as idx --获取数组的角标
from
tb_arr_join
针对上面的结果,我们想要输出bobby里面的每一个数及对应得到index
- 升级语句
SELECT
id,
name,
bobby,
arrayEnumerate(bobby) as idx, --获取数组的角标
h,
i
from
tb_arr_join
array join --拆分数组
bobby as h,
idx as i
只想要数组的元素和它的角标
SELECT
id,
name,
h,
idx
from
tb_arr_join
array join
--拆分数组
bobby as h,
arrayEnumerate(bobby) as idx
# 案例:
需求:
- 将同一个店铺中的时间收集到数组中,按照日期排序
- array join
- 日期 - 编号
- 分组 聚合
步骤:
1、创建一个shop.txt文件,放到clickhouse 的服务器下的/root/data路径下
a,2017-02-05,200 a,2017-02-06,300 a,2017-02-07,200 a,2017-02-08,200 b,2017-02-05,200 b,2017-02-06,300 b,2017-02-09,400 b,2017-02-08,200 c,2017-01-31,200 c,2017-02-01,300 c,2017-02-03,400 c,2017-02-10,600 a,2017-03-01,200 a,2017-03-02,300 a,2017-03-04,400 a,2017-03-05,600
2、创建shop表
CREATE table shop(
name String,
cdate Date,
money Float64
)engine=MergeTree()
order by (name,cdate);
3、用clickhouse-client导入shop.txt文件数据
[root@localhost data]# clickhouse-client --host localhost --user default --port 9000 --password 123456 -q 'insert into shop FORMAT CSV' < '/root/data/shop.txt'
4、查看数据是否分组
select * from shop
截止到这里,我们需求的第一步的数据已经有了
1)将同一个店铺中的时间收集到数组中,按照日期排序
SELECT name,groupArray(cdate) as dates ,arrayEnumerate(dates) as idxs from shop group by name;
2)array join
SELECT name , dy,idx from (
-- groupArray 合并成数组,arrayEnumerate 获取数组角标
SELECT name,groupArray(cdate) as dates ,arrayEnumerate(dates) as idxs from shop group by name
)
array join
dates as dy,
idxs as idx
order by dy asc;
3) 日期减编号
-- groupArray 合并成数组,arrayEnumerate 获取数组角标,subtractDays 求日期差值
SELECT name , dy,idx,subtractDays(dy,idx) sub from (
SELECT name,groupArray(cdate) as dates ,arrayEnumerate(dates) as idxs from shop group by name
)
array join
dates as dy,
idxs as idx
order by dy asc;
4)分组 聚合
SELECT
name,sub,COUNT(1) cnt
from
(
SELECT name , dy,idx,subtractDays(dy,idx) sub from (
SELECT name,groupArray(cdate) as dates ,arrayEnumerate(dates) as idxs from shop group by name
)
array join
dates as dy,
idxs as idx
order by dy asc
)
group by (name,sub)
HAVING cnt >1
order by name,cnt DESC
limit 1 by name; -- 只取一个name
3、行转列,列转行
行转列:
原始数据
需要转化成这样
-- concat 合并,groupArray合并成数组,arrayStringConcat将数组元素按照给定分隔符进行拼接(数组元素必须为String类型) SELECT xxxz,arrayStringConcat(groupArray(name),' | ') as concat_col from( SELECT name,concat(xz,',',blood_type) as xxxz from xxw )group by xxxz
列转行:
原始数据
需要转换成
-- splitByChar把字符串变成数组 SELECT name,ty from( SELECT name,splitByChar(',',types) as typ from movie ) array join typ as ty;
4、join
员工表:yg
部门表:bm
连接进度:all(符合条件的都连)、any(符合条件的只会连一个)、asof(非等值连接,可以附加一些条件)
yg join/all join/inner join bm on yg.bid=bm.bid 都是一样的,满足条件的都脸上
yg any join bm on yg.bid=bm.bid 连接上一次就不在连了
asof join yg y2 on y1.bid=y2.bid and y1.age>y2.age 用asof可以拼接这种非等值的条件,不加asof会报错
链接类型
left join:左侧表为准,right join右侧表为准
4、数组函数
5、其他重要函数
toXXX -->时间函数,还有很多下面只列举了几个常用的
- toDate():将字符日期或时间戳转化为日期
- toDateTime() :将字符时间戳转化为时间戳
- formatDateTime:函数根据给定的格式字符串来格式化时间
cast(x,t) -->将"x"转换为"t"数据类型。 也可以写成: CAST(x as t)
round()函数-->求百分比
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
2019-11-26 【线程dump详解jstack&full gc】