2011-12-27 4 views
2

Я использую Vertica, что, к сожалению, не позволяет мне использовать CROSS APPLY. И, видимо, в Vertica нет такой вещи, как CTE.еще одна дата пробел-заполнить SQL-загадка

Вот что я получил:

t: 
    day | id | metric | d_metric 
-----------+----+--------+---------- 
2011-12-01 | 1 | 10  | 10 
2011-12-03 | 1 | 12  | 2 
2011-12-04 | 1 | 15  | 3 

Обратите внимание, что в первый день, дельта равна значению метрики. Я хотел бы, чтобы заполнить пробелы, например:

t_fill: 
    day | id | metric | d_metric 
-----------+----+--------+---------- 
2011-12-01 | 1 | 10  | 10 
2011-12-02 | 1 | 10  | 0 -- a delta of 0 
2011-12-03 | 1 | 12  | 2 
2011-12-04 | 1 | 15  | 3 

Я придумал способ сделать это изо дня в день, но я бы очень хотел, это решение, которое работает на одном дыхании ,

Я думаю, что я мог бы получить что-то работающее с LAST_VALUE, но я не могу придумать правильные операторы JOIN, которые позволят мне правильно разбить и упорядочить каждую историю каждого дня.

редактировать: предположить, у меня есть таблица вроде этого:

calendar: 
    day 
------------ 
2011-01-01 
2011-01-02 
    ... 

, которые могут быть связаны с соединениями. Мое намерение состояло бы в том, чтобы поддерживать диапазон дат в календаре в соответствии с диапазоном дат в t.

редактировать: Еще несколько заметок о том, что я ищу, просто чтобы быть конкретным:

При генерации t_fill, я хотел бы, чтобы точно покрыть диапазон дат в т, а а также любые даты, отсутствующие между ними. Так что правильный t_fill начнется в тот же день и конец с той же даты, что и t. t_fill имеет два свойства:

1) один раз на некоторую дату появляется идентификатор, он всегда будет иметь строку для каждого последующего дня. Это заполнение пробелов, подразумеваемое в исходном вопросе.

2) не должны ни в одной строке для идентификатора когда-нибудь появится снова после того, как какой-то даты, то t_fill раствор должен весело генерировать строки с одной и той же значение метрики (и 0 дельта) с даты, что в последние данные указывают до конца дата t.

Решение может задерживать более ранние даты до начала диапазона дат в t. То есть для любого идентификатора, который появляется после первой даты в t, строки между первой датой в t и первая дата для идентификатора будут заполнены метрикой = 0 и d_metric = 0. Я не предпочитаю такого решения, так как он имеет более высокий коэффициент роста для каждого идентификатора, который входит в систему. Но я мог бы легко справиться с этим, выбрав в новую таблицу только строки, где metric! = 0 и d_metric! = 0.

+2

Я ничего не знаю о Vertica, но, как говорится на [их сайте] (http://www.vertica.com/the-analytics-platform/advanced-in-database-analytics/), * «Некоторые из Vertica Advanced Возможности Google Analytics включают: заполнение основного зазора, ... '*. Итак, если бы я был вами, я, вероятно, должен был начать расследование в этом направлении. –

+0

Мы пробовали свои функции GFI в прошлом, но у этого есть очень специфический склон, который не устраивает наши потребности здесь. – kimbo305

+0

Что конкретно не соответствует вашим потребностям? Кажется, что заполнение пробелов с постоянной интерполяцией было бы способом пойти. – geoffrobinson

ответ

0

Я не являюсь пользователем Vertica, но если вы не хотите использовать их родную поддержку GAP fillings, here, вы можете найти более общее решение SQL-only для этого.

+0

Я видел, что один и попробовал чтобы адаптировать его, прежде чем начинать этот ответ. Проблема, с которой я столкнулся, заключается в том, что LEFT JOIN не помогает мне заполнять значения id. Таблица в этой ссылке в основном жестких кодов для одного id, поэтому LEFT JOIN по-прежнему жизнеспособна. – kimbo305

0

Если вы хотите использовать что-то вроде CTE, как насчет использования временной таблицы? По существу, CTE представляет собой представление для конкретного запроса.

В зависимости от ваших потребностей вы можете выполнить временную транзакцию таблицы или зону сеанса.

Мне все еще интересно узнать, почему заполнение пробелов с постоянной интерполяцией здесь не работает.

+0

Я думаю, что отвечу на это первым, как первый шаг к ответу на вопрос Джонатана. Есть два типа диапазонов дат, с которыми мы имеем дело. – kimbo305

+0

e (goofed the comment): Первый - это диапазон дат запроса к новой таблице, которую мы собираем построить. Второй - это диапазон дат для каждого идентификатора в исходной таблице метрик ** t **. История метрик id может начинаться хорошо после первого дня, для которого у нас есть какие-либо данные. Иногда он также может остановиться. И, конечно же, как мы видели, у него могут отсутствовать промежутки времени между ними. Диапазон дат запроса может полностью пропустить некоторые идентификаторы. Когда это происходит, заполнение пробелов, реализованное как TIMESERIES в Vertica, ничего не делает. Поскольку в захваченном диапазоне дат нет данных для работы. – kimbo305

0

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

Ваш запрос должен быть указан умеренно точно, что обычно составляет половину сражения в любой проблеме с «как написать запрос». Я думаю, что вы ищете:

  • За каждую дату в календаре между минимальным и максимальным датами, представленными в T (или другого оговоренного диапазона),
  • Для каждого отдельного ID представленного в T,
  • Найдите метрика для данного идентификатора для самой последней записи в T до или до даты.

Это дает вам полный список дат с метриками.

Затем вам необходимо объединить две копии этого списка с датами на один день, чтобы сформировать дельт.

Обратите внимание, что если некоторые значения идентификатора не отображаются в начале диапазона дат, они не будут отображаться.

С этим, как и руководство, вы должны быть в порядке, я верю.

+0

> Обратите внимание, что если некоторые значения ID не отображаются в начале диапазона дат, они не будут отображаться. Именно поэтому мы ищем создание новой таблицы из ** t **. – kimbo305

+0

Проблема в том, что у вас нет ничего, что можно было бы использовать для идентификатора, который появляется через 3 дня после начала. Вы хотите иметь нули для таких записей? –

+0

e: dang. Так плохо, что не попадайте в комментарии. Цель заполнения этого пробела - это не просто пробелы, но и заполнение истории каждого идентификатора с последней строки/даты, для которой у нее есть данные до последней даты запроса: http: // stackoverflow. com/questions/8640626/yet-another-date-gap-fill-sql-puzzle/8714804 # 8714804 Как вы можете видеть, с наивным запросом на ** t **, любые идентификаторы, история которых заканчивается до начала дата запроса не будет отображаться вообще. В этом проблема с использованием решения Vertica TIMESERIES, а также проблема с (моей интерпретацией) предостережения, приведенного выше. – kimbo305

1

Это о том, что предложил Джонатан Леффлера, но в старомодном низкоуровневого SQL (без фантазии CTE-х или оконных функций или агрегирования подзапросов):

SET search_path='tmp' 
DROP TABLE ttable CASCADE; 
CREATE TABLE ttable 
     (zday date NOT NULL 
     , id INTEGER NOT NULL 
     , metric INTEGER NOT NULL 
     , d_metric INTEGER NOT NULL 
     , PRIMARY KEY (id,zday) 
     ); 
INSERT INTO ttable(zday,id,metric,d_metric) VALUES 
('2011-12-01',1,10,10) 
,('2011-12-03',1,12,2) 
,('2011-12-04',1,15,3) 
     ; 

DROP TABLE ctable CASCADE; 
CREATE TABLE ctable 
     (zday date NOT NULL 
     , PRIMARY KEY (zday) 
     ); 
INSERT INTO ctable(zday) VALUES 
('2011-12-01') 
,('2011-12-02') 
,('2011-12-03') 
,('2011-12-04') 
     ; 

CREATE VIEW v_cte AS (
     SELECT t.zday,t.id,t.metric,t.d_metric 
     FROM ttable t 
     JOIN ctable c ON c.zday = t.zday 
     UNION 
     SELECT c.zday,t.id,t.metric, 0 
     FROM ctable c, ttable t 
     WHERE t.zday < c.zday 
     AND NOT EXISTS (SELECT * 
       FROM ttable nx 
       WHERE nx.id = t.id 
       AND nx.zday = c.zday 
       ) 
     AND NOT EXISTS (SELECT * 
       FROM ttable nx 
       WHERE nx.id = t.id 
       AND nx.zday < c.zday 
       AND nx.zday > t.zday 
       ) 
     ) 
     ; 
SELECT * FROM v_cte; 

Результаты:

zday | id | metric | d_metric 
------------+----+--------+---------- 
2011-12-01 | 1 |  10 |  10 
2011-12-02 | 1 |  10 |  0 
2011-12-03 | 1 |  12 |  2 
2011-12-04 | 1 |  15 |  3 
(4 rows) 
+0

У меня наконец появился шанс реализовать это. Я считаю, что это работает, но масштаб невелик. В исходной таблице t содержится около 500 строк в строке, и все эти SELECT в NOT EXISTs являются большой болью. – kimbo305

+0

Не говорите слишком рано: 'не существует' подзапросы обычно обрабатываются неожиданно эффективно (вероятно, потому, что конструкция довольно старая). Но я не знаю о вашей платформе/реализации. – wildplasser

+0

Я рассмотрю план запроса, представленный мне с поддержкой Vertica. – kimbo305

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