【发布时间】:2017-04-05 09:55:48
【问题描述】:
我以为我对 SQL 很了解,直到我想创建看似简单的东西:
- 按 id 显示项目计数的聚合直方图;
- 按 1 分钟等时间间隔分布;
- 所有 id 的直方图必须具有相同的时间间隔和槽;
- 所以如果该时间段内没有条目,则应使用 0 填充间隙;
- 按总计数顺序排列。
我想一定有一些基本的聚合函数允许在 Vertica 中执行此操作,但这是我在 SQL 中能想到的最好的方法,我真的不喜欢我设法想出的东西 - 特别是对于大量数据,这种方法非常糟糕,因为它会消耗大量内存(请注意 CROSS JOIN 野兽)。
输入数据:
项目表(重复的id,created_at)
CREATE TABLE items(id int, created_at timestamp);
INSERT INTO items(id, created_at) VALUES (1, '2016-01-02 00:00:00');
INSERT INTO items(id, created_at) VALUES (1, '2016-01-02 00:01:01');
INSERT INTO items(id, created_at) VALUES (2, '2016-01-02 00:05:10');
INSERT INTO items(id, created_at) VALUES (2, '2016-01-02 00:05:12');
INSERT INTO items(id, created_at) VALUES (3, '2016-01-02 00:05:01');
INSERT INTO items(id, created_at) VALUES (3, '2016-01-02 00:05:04');
INSERT INTO items(id, created_at) VALUES (3, '2016-01-02 00:05:30');
INSERT INTO items(id, created_at) VALUES (3, '2016-01-02 00:02:05');
INSERT INTO items(id, created_at) VALUES (3, '2016-01-02 00:20:02');
预期结果:
执行此操作的我的 SQL 查询版本:
(我现在真的很惭愧……)
SELECT
a.id,
sum(a.count) AS total_count,
agg_concatenate(a.count||',') AS histogram
FROM (
SELECT
i.id,
times.ts,
nvl(counts.count,0) AS count
FROM (
SELECT ts FROM (
SELECT '2016-01-02 00:00:00'::TIMESTAMP AS tm
UNION ALL
SELECT '2016-01-02 00:20:00'::TIMESTAMP AS tm
) t
TIMESERIES ts AS '1 minute' OVER (ORDER BY tm)) times
CROSS JOIN (
SELECT DISTINCT id FROM items
) i
LEFT OUTER JOIN (
SELECT
time_slice(created_at, 1, 'MINUTE') AS ts,
id,
count(*) AS count
FROM
items
GROUP BY
1,2) counts ON counts.ts=times.ts AND counts.id=i.id
ORDER BY 1,2
) a
GROUP BY
a.id
ORDER BY
2 DESC;
考虑的其他可能性
当然有另一种方法可以用 Java、C++ 或其他语言编写自定义 Vertica 用户定义扩展,但在此之前,我真的想确保我不会错过一些简单的解决方案,如何做到这一点。
Vertica 是一种数据库平台,人们会期望存在这样的东西,只是可能我在阅读手册时不够仔细......
如果您是 Vertica 方面的专家,或者知道使用普通 SQL 的更好解决方案,那么您会很高兴找到这一点。 即使您知道一个现有的 UDX,也会有所帮助。主要的事情 - 我希望这个计算尽可能接近数据。
谢谢!
马里斯
【问题讨论】:
标签: sql time-series histogram vertica