2017-01-17 3 views
0

Необходимо повернуть матрицу, чтобы выполнить интерполяцию интервалов/интервалов TIMESERIES, и хотелось бы избежать беспорядочного подхода UNION ALL. Есть ли что-то вроде функции HATER LATERAL VIEW EXPLODE, доступной в Vertica?Vertica - Есть ли функция LATERAL VIEW?

EDIT: @marcothesane - спасибо за ваш интересный сценарий - мне нравится ваш подход к интерполяции. Я буду играть с ним больше и посмотреть, как это происходит. Выглядит многообещающе.

FYI - вот решение, с которым я столкнулся - мой сценарий заключается в том, что я пытаюсь просматривать использование памяти с течением времени по запросу (и пул пользователей/ресурсов и т. Д., В основном пытающийся получить показатель стоимости) , Мне нужно сделать интерполяцию, чтобы я мог видеть общее использование в любой момент времени. Итак, вот мой запрос, который делает временные ряды нарезкой на секунду, а затем агрегаты, чтобы дать метрику «Megabyte_Seconds» поминутно.

with qry_cte as 
(
select 
session_id 
, request_id 
, date_trunc('second',start_timestamp) as dat_str 
, timestampadd('ss' 
    , ceiling(request_duration_ms/1000)::int 
    , date_trunc('second',start_timestamp) 
    ) as dat_end 
, ceiling(request_duration_ms/1000)::int as secs 
, memory_acquired_mb 
from query_requests 
where request_type = 'QUERY' 
and request_duration_ms > 0 
and memory_acquired_mb > 0 
) 

select date_trunc('minute',slice_time) as dat_minute 
, count(distinct session_id || request_id::varchar) as queries 
, sum(memory_acquired_mb) as mb_seconds 
from (
select session_id, request_id, slice_time, ts_first_value(memory_acquired_mb) as memory_acquired_mb 
from (
select session_id, request_id, dat_str as dat, memory_acquired_mb from qry_cte 
union all 
select session_id, request_id, dat_end as dat, memory_acquired_mb from qry_cte 
) x 
timeseries slice_time as '1 second' over (partition by session_id, request_id order by dat) 
) x 
group by 1 order by 1 desc 
; 
+0

Как вы можете легко проверить: есть нет таких "LATERAL VIEW взрываются" в Vertica SQL Reference Manual. Но ... если вы добавите образцы входных данных и желаемый результат, кто-то сможет найти решение. – mauro

ответ

2

Я на самом деле есть сценарий под рукой, который мог бы соответствовать вашим требованиям:

Из этого:

id|day_strt   |sales_01 |sales_02 |sales_03 |sales_04 |sales_05 |sales_06 
1|2016-01-19 08:00:00| 1,842.25| 5,449.40|-  |39,776.86|-  | 9,424.10 
2|2016-01-19 08:00:00|73,810.66|-  | 9,867.70|-  |76,723.91|95,605.14 

Сделать это:

id|day_strt   |sales_01 |sales_02 |sales_03 |sales_04 |sales_05 |sales_06 
1|2016-01-19 08:00:00| 1,842.25| 5,449.40|22,613.13|39,776.86|24,600.48| 9,424.10 
2|2016-01-19 08:00:00|73,810.66|41,839.18| 9,867.70|43,295.81|76,723.91|95,605.14 

01 через 06 относится к n-й час дня, когда были зарегистрированы продажи, начиная с 08:00.

Ниже приведен весь сценарий, включая исходные входные данные.

  1. входные данные как SELECT .. UNION ALL SELECT ....
  2. Таблица, состоящая из 6 целых чисел, к CROSS JOIN к таблице 1.
  3. Вертикальная ось: перекрестное соединение ввода с целыми числами 6 и в зависимости от индекса выводит только n-й столбец продаж в Выражение CASE. Наконец, отфильтруйте все те же выражения CASE, что и NULL.
  4. Заполните пробелы, используя предложение TIMESERIES и линейную интерполяцию: показатели продаж, а также колонку индексирования.
  5. Горизонтальный поворот все снова в последнем запросе.

Больше, чем UNION ALL по всем столбцам таблицы, я могу вам это гарантировать.

Здесь идет:

WITH 
-- input 
input(id,day_strt,sales_01,sales_02,sales_03,sales_04,sales_05,sales_06) AS (
      SELECT 1,'2016-01-19 08:00:00'::TIMESTAMP(0), 1842.25, 5449.40 ,NULL::INT,39776.86 ,NULL::INT, 9424.10 
UNION ALL SELECT 2,'2016-01-19 08:00:00'::TIMESTAMP(0),73810.66 ,NULL::INT, 9867.70 ,NULL::INT,76723.91 ,95605.14 
) 
-- debug 
-- SELECT * FROM input; 
, 
-- 6 months to pivot vertically -> 6 integers 
six_idxs(idx) AS (
      SELECT 1 
UNION ALL SELECT 2 
UNION ALL SELECT 3 
UNION ALL SELECT 4 
UNION ALL SELECT 5 
UNION ALL SELECT 6 
) 
, 
-- pivot input vertically and remove rows with null measures 
-- (could probably add the TIMESERIES clause here directly, 
-- but less readable and maintainable) 
vert_pivot AS (
SELECT 
    id 
, idx 
, TIMESTAMPADD(HOUR,idx-1,day_strt)::TIMESTAMP(0) AS sales_ts 
, CASE idx 
    WHEN 1 THEN sales_01 
    WHEN 2 THEN sales_02 
    WHEN 3 THEN sales_03 
    WHEN 4 THEN sales_04 
    WHEN 5 THEN sales_05 
    WHEN 6 THEN sales_06 
    END AS sales 
FROM input 
CROSS JOIN six_idxs 
WHERE (
    CASE idx 
     WHEN 1 THEN sales_01 
     WHEN 2 THEN sales_02 
     WHEN 3 THEN sales_03 
     WHEN 4 THEN sales_04 
     WHEN 5 THEN sales_05 
     WHEN 6 THEN sales_06 
    END 
) IS NOT NULL 
) 
-- debug: 
-- SELECT * FROM vert_pivot; 
, 
-- gap filling and interpolation 
gaps_filled AS (
SELECT 
    id 
, TS_FIRST_VALUE(idx,'LINEAR') AS idx 
, tm_sales_ts::TIMESTAMP(0) AS sales_ts 
, TS_FIRST_VALUE(sales,'LINEAR') AS sales 
FROM vert_pivot 
TIMESERIES tm_sales_ts AS '1 HOUR' OVER(
    PARTITION BY id ORDER BY sales_ts 
) 
) 
-- debug 
-- SELECT * FROM gaps_filled ORDER BY 1,2; 
-- pivot horizontally; final query 
SELECT 
    id 
, MIN(sales_ts) AS day_strt 
, SUM(CASE idx WHEN 1 THEN sales END)::NUMERIC(7,2) AS sales_01 
, SUM(CASE idx WHEN 2 THEN sales END)::NUMERIC(7,2) AS sales_02 
, SUM(CASE idx WHEN 3 THEN sales END)::NUMERIC(7,2) AS sales_03 
, SUM(CASE idx WHEN 4 THEN sales END)::NUMERIC(7,2) AS sales_04 
, SUM(CASE idx WHEN 5 THEN sales END)::NUMERIC(7,2) AS sales_05 
, SUM(CASE idx WHEN 6 THEN sales END)::NUMERIC(7,2) AS sales_06 
FROM gaps_filled 
GROUP BY id 
ORDER BY id 
; 

счастливы игры -

Marco здравомыслящий