Я думал, что я знаю, что SQL достаточно хорошо, пока я не хотел, чтобы создать, казалось бы, простой вещь:Vertica SQL: Гистограмма отсчетов из данных временных рядов с пропусками
- агрегированной гистограмма, которая показывает количество элементов по идентификатору;
- распределяется равномерно на 1 мин;
- гистограммы для всех идентификаторов должны иметь одинаковые временные интервалы и интервалы;
- поэтому, если в этот временной интервал не было записей, пробелы должны быть заполнены 0;
- по общей сумме убываний.
Я предполагаю, что должна быть какая-то элементарная функция агрегата, которая позволяет это делать в Vertica, но вот лучшее, что я могу придумать в SQL, и мне действительно не нравится то, что мне удалось подойти с - особенно для большого количества данных, этот подход действительно плох, потому что он будет потреблять космические объемы памяти (обратите внимание на CROSS JOIN beast).
Входные данные:
Таблица элементов (идентификатор, который повторяет, 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 Query, который делает это:
(я на самом деле стыдно сейчас ...)
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;
Другие возможности Рассматриваемые
Существует с курса альтернативу написанию пользовательского пользовательского расширенного расширения Vertica на Java, C++ или на другом языке, но перед этим я действительно хотел убедиться, что я не пропустил som Простое решение, как это сделать.
Vertica является своего рода база данных платформы, на которой можно было бы ожидать, такая вещь существует, просто, может быть, я не был достаточно осторожен в чтении руководства ...
Если вы являетесь экспертом в Vertica или знать лучшее решение в простом SQL, было бы неплохо найти это. Даже если вы знаете существующий UDX для этого, также было бы полезно. Главное - я хочу, чтобы это было рассчитано как можно ближе к данным.
Спасибо!
Maris