2016-12-01 22 views
3

Рассмотрим столбец, который представляет «время между событиями»:Sessionize столбец чисел на группы по 30 раз порог встречается в Teradata

(5, 40, 3, 6, 0, 9, 0, 4, 5, 18, 2, 4, 3, 2)

Я хотел бы сгруппировать их в ведра 30, но ведра, которые перезагружаются. Желаемый результат:

(0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2)

Это происходит потому, что, когда мы получаем к совокупному 30, мы «сброс» и начать отсчет снова. Итак, 5 + 40> 30, мы опустимся до нуля и начнем кумулятивное добавление до тех пор, пока не достигнем 30 ... (3 + 6 + 0 ...), которое происходит при достижении 10-го элемента == 18.

Это может быть реализовано с помощью функции Reduce (см. this answer), но я не могу понять, как реализовать это в Teradata? Это похоже на то, что я должен иметь возможность ссылаться на тот же OVER(PARTITION BY ... в рамках одного и того же вызова.


Ломая логику, вот пример в Excel:

enter image description here

Где, B2 имеет формулу: =IF(B1<30, B1+A2, A2) и замедлен, соответственно. Столбец C затем проверяет, стоит ли столбец B> = 30, а столбец D - это простая запись из столбца B.

+0

есть ли какой-либо столбец, определяющий заказ? –

+0

Предположим, что «время между» уже в порядке. Но да, на самом деле, вы можете подумать, что будут два дополнительных столбца: 'cust_id' и' event_time'. Таким образом, куча опций «OVER (PARTITION» будет «OVER (PARTITION by cust_id ORDER BY event_time ROWS ...» – JasonAizkalns

+0

@vkp см. Мой комментарий выше для ясности и дайте мне знать, если вы думаете, что его следует добавить к вопросу – JasonAizkalns

ответ

3

Только способ, которым я знаю это сделать в Teradata, - использовать рекурсивный CTE. Потому что я ленив, давайте упростить это вниз, чтобы сказать, что вы хотите сбросить, когда ваша текущая сумма больше, чем 2. Создание и заполнение очень простой летучий таблицу для этого:

CREATE VOLATILE TABLE vt1 
(
    foo VARCHAR(10) 
    , counter INTEGER 
    , bar INTEGER 
) 
ON COMMIT PRESERVE ROWS; 

INSERT INTO vt1 VALUES ('a', 1, '1'); 
INSERT INTO vt1 VALUES ('a', 2, '2'); 
INSERT INTO vt1 VALUES ('a', 3, '2'); 
INSERT INTO vt1 VALUES ('a', 4, '4'); 
INSERT INTO vt1 VALUES ('a', 5, '1'); 
INSERT INTO vt1 VALUES ('b', 1, '3'); 
INSERT INTO vt1 VALUES ('b', 2, '1'); 
INSERT INTO vt1 VALUES ('b', 3, '1'); 
INSERT INTO vt1 VALUES ('b', 4, '2'); 

Вот фактический выбор:

WITH RECURSIVE cte (foo, counter, bar, rsum) AS 
(
SELECT 
    foo 
    , counter 
    , bar 
    , bar AS rsum 
FROM 
    vt1 
QUALIFY ROW_NUMBER() OVER (PARTITION BY foo ORDER BY counter) = 1 

UNION ALL 

SELECT 
    t.foo 
    , t.counter 
    , t.bar 
    , CASE WHEN cte.rsum < 3 THEN t.bar + cte.rsum ELSE t.bar END 
FROM 
    vt1 t JOIN cte ON t.foo = cte.foo AND t.counter = cte.counter + 1 
) 

SELECT 
    cte.* 
    , CASE WHEN rsum < 5 THEN 0 ELSE 1 END AS tester 
FROM 
    cte 
ORDER BY 
    foo 
    , counter 
; 

Что будет, наконец, дать нам:

╔═════╦═════════╦═════╦══════╦════════╗ 
║ foo ║ counter ║ bar ║ rsum ║ tester ║ 
╠═════╬═════════╬═════╬══════╬════════╣ 
║ a ║  1 ║ 1 ║ 1 ║  0 ║ 
║ a ║  2 ║ 2 ║ 3 ║  0 ║ 
║ a ║  3 ║ 2 ║ 5 ║  1 ║ 
║ a ║  4 ║ 4 ║ 4 ║  0 ║ 
║ a ║  5 ║ 1 ║ 5 ║  1 ║ 
║ b ║  1 ║ 3 ║ 3 ║  0 ║ 
║ b ║  2 ║ 1 ║ 4 ║  0 ║ 
║ b ║  3 ║ 1 ║ 5 ║  1 ║ 
║ b ║  4 ║ 2 ║ 2 ║  0 ║ 
╚═════╩═════════╩═════╩══════╩════════╝ 

заявления тематические ручки сброса для нас.

Это некрасиво, но я никогда не мог заставить это работать каким-либо другим способом.

+0

Согласен, что это уродливый, но полезный +1 - я не знаком с CTE, поэтому я буду играть с этим завтра, но вы можете расширить или обобщить свой пример для: (a) разделение по полю id, которое не все одинаково повсюду (я не уверен, что я следую за тем, почему foo возвращает 1: 5, и (б) показывает, как вещи изменяются при расширении до суммы, превышающей 4?Срабатывает ли счетная логика? – JasonAizkalns

+1

Извините, паста для результатов была фанки, проверьте ее сейчас. Счетчик является просто упрощенным столбцом для порядка в разделе раздела. Это может быть дата или что-то еще. Я также расширил данные в CTE. – Andrew

+0

Теперь у вас гораздо больше смысла. Спасибо. Продолжая оставлять это без ответа немного, чтобы узнать, может ли кто-нибудь еще придумать альтернативный или менее неуклюжий подход. – JasonAizkalns