2016-11-21 2 views
2

Я думал, что я знаю, что SQL достаточно хорошо, пока я не хотел, чтобы создать, казалось бы, простой вещь:Vertica SQL: Гистограмма отсчетов из данных временных рядов с пропусками

  • агрегированной гистограмма, которая показывает количество элементов по идентификатору;
  • распределяется равномерно на 1 мин;
  • гистограммы для всех идентификаторов должны иметь одинаковые временные интервалы и интервалы;
  • поэтому, если в этот временной интервал не было записей, пробелы должны быть заполнены 0;
  • по общей сумме убываний.

Я предполагаю, что должна быть какая-то элементарная функция агрегата, которая позволяет это делать в Vertica, но вот лучшее, что я могу придумать в SQL, и мне действительно не нравится то, что мне удалось подойти с - особенно для большого количества данных, этот подход действительно плох, потому что он будет потреблять космические объемы памяти (обратите внимание на CROSS JOIN beast).

Входные данные:

Input Data

Таблица элементов (идентификатор, который повторяет, 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'); 

Ожидаемые результаты:

Histogram

Моя версия 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

ответ

0

Это не выглядит плохо.Я не знаю ни каких-либо элегантных уловок для вашей области гистограммы:

agg_concatenate(a.count||',') 

Главное - я хочу, чтобы это было рассчитано как можно ближе к данным, как это возможно.

Такой тип конкатенации - это то, что я сделал бы в Excel или вне SQL, если это необходимо, но я понимаю, что должен иметь особые ограничения на то, где данные хрустят.

Является ли выполнение запроса действительно медленным для ваших нужд или чего-то еще?

 Смежные вопросы

  • Нет связанных вопросов^_^