Как написать запрос для добавления номера (от 1 до n) к каждой записи для каждой группы - PullRequest
0 голосов
/ 11 июня 2019

У меня есть набор данных, подобный приведенному ниже

|date|flag|
|20190503|0|
|20190504|1|
|20190505|1|
|20190506|1|
|20190507|1|
|20190508|0|
|20190509|0|
|20190510|0|
|20190511|1|
|20190512|1|
|20190513|0|
|20190514|0|
|20190515|1|

Чего я хочу добиться, это сгруппировать последовательные даты по флагу = 1 и добавить один счетчик столбцов к отметке 1 для первого дня последовательногодни, когда флаг = 1, и 2 для 2-го дня и т. д., присваивают 0 для флага = 0

|date|flag|counter|
|20190503|0|0|
|20190504|1|1|
|20190505|1|2|
|20190506|1|3|
|20190507|1|4|
|20190508|0|0|
|20190509|0|0|
|20190510|0|0|
|20190511|1|1|
|20190512|1|2|
|20190513|0|0|
|20190514|0|0|
|20190515|1|1|

Я пробовал аналитическую функцию и запрос иерархии, но все еще не нашел решения, ищу помощь,Любой намек приветствуется!

Спасибо, Hong

Ответы [ 2 ]

1 голос
/ 11 июня 2019

Вы можете определить группы, используя кумулятивную сумму нулей. Тогда используйте row_number():

select t.*,
       (case when flag = 0 then 0
             else row_number() over (partition by grp order by date)
        end) as counter
from (select t.*,
             sum(case when flag = 0 then 1 else 0 end) over (order by date) as grp
      from t
     ) t;

Совсем другой подход - взять разницу между текущей датой и кумулятивным максимумом даты flag = 0:

select t.*,
       datediff(day,
                max(case when flag = 0 then date end) over (order by date),
                date
               ) as counter
from t;

Обратите внимание, что логика этих двух подходов различна - хотя они должны давать одинаковые результаты для предоставленных вами данных. Для пропущенных дат первое просто игнорирует пропущенные даты. Второй будет увеличивать счетчик для пропущенных дат.

0 голосов
/ 11 июня 2019

Хорошо - у Vertica есть очень хорошая функция CONDITIONAL_CHANGE_EVENT (), которая могла бы вам помочь ...

Каждый раз, когда изменяется выражение в скобках, целое число увеличивается на 1. Это дает вам новый идентификатор группыили критерий для PARTITION BY при каждом изменении flag.Таким образом, один ВЫБРАТЬ, чтобы получить информацию о группировке, а затем разделить полученную информацию о группировке.Здесь идет:

WITH
input(dt,flag) AS (
          SELECT '2019-05-03'::DATE,0
UNION ALL SELECT '2019-05-04'::DATE,1
UNION ALL SELECT '2019-05-05'::DATE,1
UNION ALL SELECT '2019-05-06'::DATE,1
UNION ALL SELECT '2019-05-07'::DATE,1
UNION ALL SELECT '2019-05-08'::DATE,0
UNION ALL SELECT '2019-05-09'::DATE,0
UNION ALL SELECT '2019-05-10'::DATE,0
UNION ALL SELECT '2019-05-11'::DATE,1
UNION ALL SELECT '2019-05-12'::DATE,1
UNION ALL SELECT '2019-05-13'::DATE,0
UNION ALL SELECT '2019-05-14'::DATE,0
UNION ALL SELECT '2019-05-15'::DATE,1
)
,
grp_input AS (
SELECT
*
, CONDITIONAL_CHANGE_EVENT(flag) OVER(ORDER BY dt) AS grp
FROM input
)
SELECT
dt
, flag
, CASE FLAG
WHEN 0 THEN 0
ELSE ROW_NUMBER() OVER(PARTITION BY grp ORDER BY dt)
END AS counter
FROM grp_input;
-- out      dt     | flag | counter 
-- out ------------+------+---------
-- out  2019-05-03 |    0 |       0
-- out  2019-05-04 |    1 |       1
-- out  2019-05-05 |    1 |       2
-- out  2019-05-06 |    1 |       3
-- out  2019-05-07 |    1 |       4
-- out  2019-05-08 |    0 |       0
-- out  2019-05-09 |    0 |       0
-- out  2019-05-10 |    0 |       0
-- out  2019-05-11 |    1 |       1
-- out  2019-05-12 |    1 |       2
-- out  2019-05-13 |    0 |       0
-- out  2019-05-14 |    0 |       0
-- out  2019-05-15 |    1 |       1
-- out (13 rows)
-- out 
...