在ClickHouse中按组查询前N行的正确方法是什么?
让我们以tbl具有id2,id4,v3列且N = 2的示例为例。
我尝试了以下
SELECT
id2,
id4,
v3 AS v3
FROM tbl
GROUP BY
id2,
id4
ORDER BY v3 DESC
LIMIT 2 BY
id2,
id4
但出现错误
Received exception from server (version 19.3.4):
Code: 215. DB::Exception: Received from localhost:9000, 127.0.0.1. DB::Exception
: Column v3 is not under aggregate function and not in GROUP BY..
我可以将v3
放在GROUP BY中,它的确起作用,但是按度量标准分组效率不高。
有any
个聚合函数,但实际上我们希望all
的值(由LIMIT BY子句限制为2)不是any
的值,因此听起来并不恰当解决方案在这里。
SELECT
id2,
id4,
any(v3) AS v3
FROM tbl
GROUP BY
id2,
id4
ORDER BY v3 DESC
LIMIT 2 BY
id2,
id4
答案 0 :(得分:1)
可以aggregate functions这样使用它:
Compose
答案 1 :(得分:1)
您也可以按照此 thread
中所述的方式在“普通”SQL 中执行此操作虽然 vladimir 的解决方案适用于许多情况,但对我的情况却不起作用。我有一张桌子,看起来像这样:
column | group by
++++++++++++++++++++++
A | Yes
B | Yes
C | No
现在,假设 A 列标识用户,B 列代表用户可以执行的任何操作 e。 G。在您的网站或您的在线游戏中。 C 列是用户执行此特定操作的频率的总和。 Vladimir 的解决方案允许我获取 A 列和 C 列,但不能获取用户执行的操作(B 列),这意味着我将知道用户某事 的频率,但不知道 什么.
这样做的原因是按 A 和 B 分组是没有意义的。每一行都是一个唯一的组,您无法找到前 K 行,因为每个组只有 1 个成员。结果与您查询的表相同。相反,如果您仅按 A 分组,则可以应用 vladimir 的解决方案,但只会得到 A 列和 C 列。您无法输出 B 列,因为它不是所解释的 Group By 语句的一部分。
如果您想获得用户执行的前 2 个(或前 5 个,或前 100 个)操作,您可能会寻找以下解决方案:
SELECT rs.id2, rs.id4, rs.v3
FROM (
SELECT id2, id4, v3, row_number()
OVER (PARTITION BY id2, id4 ORDER BY v3 DESC) AS Rank
FROM tbl
) rs WHERE Rank <= 2
注意:要使用它,您必须设置 allow_experimental_window_functions = 1
。