想必大家对hive实现分区内排名已经掌握的很好了,这篇文章主要就是将的就是用clickhouse如何实现
测试数据| store_code | sale_amt |
|---|---|
| 6819 | 29 |
| 9974 | 111 |
| 9974 | 60 |
| 9974 | 2061 |
| 4376 | 6 |
| 8677 | 24 |
| 8677 | 12 |
| 3483 | 52 |
| 3483 | 1638 |
| 3483 | 108 |
| 3483 | 24 |
| 3483 | 105 |
| 3483 | 53 |
| 3483 | 1299 |
| 9974 | 120 |
| 9974 | 27 |
| 9974 | 3980 |
| 9974 | 2198 |
| 4376 | 288 |
| 8677 | 15 |
| 8677 | 120 |
| 8677 | 53 |
| 8677 | 19 |
| 3483 | 1128 |
| 3483 | 1653 |
| 3483 | 48 |
| 3483 | 228 |
| 3483 | 11 |
| 3483 | 73 |
-- 建表语句,我是csv导入的 所以用,分割的 create table store_test ( store_code string,sale_amt int) row format delimited fields terminated by ","; -- 数据导入 看自己的实际情况 hdfs dfs -put store_code.csv /user/hive/warehouse/tmp.db/store_test --查询语句 select store_code ,sale_amt ,row_number() over(partition by store_code order by sale_amt desc) row_num from store_test;
但是clickhouse 没有 row_number() 函数 该如何实现呢?其实clickhouse是有很多函数的,让我们往下看
clickhouse实现-- 建表语句 create table tmp.store_test (store_code String, sale_amt Float32 )ENGINE=TinyLog; --数据导入语 --我直接通过dbever 导入csv文件的 -- 查询sql select * from ( select store_code,groupArray(sale_amt) as arr_sale_amt , arrayEnumerate(arr_sale_amt) AS row_number from ( select * from tmp.store_test order by sale_amt desc ) a group by store_code ) a ARRAY JOIN row_number , arr_sale_amt order by store_code ;
其中我们需要注意的就是一下几个函数了:
先将原始数据排序,因为groupArray不确定顺序
order by sale_amt desc
创建参数值所有数据的数组。 值可以按任何(不确定)顺序添加到数组中。第二个版本(带有 max_size 参数)将结果数组的大小限制为 max_size 个元素。 例如, groupArray (1) (x) 相当于 [any (x)] 。在某些情况下,您仍然可以依赖执行顺序。这适用于SELECt(查询)来自使用了 ORDER BY 子查询的情况。
groupArray(sale_amt)
返回数组中的元素下标或者说个数 Array [1, 2, 3, …, length (arr) ],此功能通常与ARRAY JOIN
一起使用。它允许在应用ARRAY JOIN后为每个数组计算一次
arrayEnumerate(arr_sale_amt)
对于包含数组列的表来说是一种常见的操作,用于生成一个新表,该表具有包含该初始列中的每个单独数组元素的列,而其他列的值将被重复显示。 这是ARRAY JOIN 语句最基本的场景。 类似于 arrayJoin 功能获取每一行并将他们展开到多行(unfold)。而聚合函数则是将多行压缩到一行中(fold或reduce)。其实就是将数组列那行数据打散到多行中。
ARRAY JOIN
-- 再单独举个官方的列子(clickhouse官网的https://clickhouse.com/docs/en/sql-reference/statements/select/array-join)
CREATE TABLE arrays_test
(
s String,
arr Array(UInt8)
) ENGINE = Memory;
INSERT INTO arrays_test
VALUES ('Hello', [1,2]), ('World', [3,4,5]), ('Goodbye', []);
┌─s───────────┬─arr─────┐
│ Hello │ [1,2] │
│ World │ [3,4,5] │
│ Goodbye │ [] │
└─────────────┴─────────┘
SELECT s, arr FROM arrays_test ARRAY JOIN arr;
┌─s─────┬─arr─┐
│ Hello │ 1 │
│ Hello │ 2 │
│ World │ 3 │
│ World │ 4 │
│ World │ 5 │
└───────┴─────┘
-- 下一个示例使用 LEFT ARRAY JOIN 子句:
SELECt s, arr
FROM arrays_test
LEFT ARRAY JOIN arr;
┌─s───────────┬─arr─┐
│ Hello │ 1 │
│ Hello │ 2 │
│ World │ 3 │
│ World │ 4 │
│ World │ 5 │
│ Goodbye │ 0 │
└─────────────┴─────┘
小伙伴们可能会觉的clickhouse会比较复杂,我们不妨换个角度想,是不是lickhouse很灵活呢?
假如我现在要实现的是要分区范围内topN呢? 就top 1吧,hive是不是还有在外面包一层 where row_num =1;如果是clickhouse的话 就可以直接groupArray(1)(sale_amt) 就行了。是不是觉得很自由 哈哈。当然clickhouse还有其他的实现方式,这里只展示这一种,而且还有特别多的函数等待着大家的挖掘吧,包括我之前有用过的漏斗分析、留存分析等。



