Плотный ранг, разделенный на столбец A, увеличенный изменением в столбце B, но упорядоченный по столбцу C - PullRequest
0 голосов
/ 08 октября 2018

У меня есть такая таблица

name|subtitle|date
ABC|excel|2018-07-07
ABC|excel|2018-08-08
ABC|ppt|2018-09-09
ABC|ppt|2018-10-10
ABC|excel|2018-11-11
ABC|ppt|2018-12-12
DEF|ppt|2018-12-31

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

name|subtitle|date|Group_Number
ABC|excel|2018-07-07|1
ABC|excel|2018-08-08|1
ABC|ppt|2018-09-09|2
ABC|ppt|2018-10-10|2
ABC|excel|2018-11-11|3
ABC|ppt|2018-12-12|4
DEF|ppt|2018-12-31|1

проблема в том, еслиЯ делаю Dense_rank () over (разделение по именам по субтитрам), тогда эта группа не только объединит все субтитры в одну группу, но и уберет порядок по дате.Я также пытался использовать функцию запаздывания, но это не очень полезно, когда вы пытаетесь увеличить столбец.

Есть ли простой способ добиться этого?

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

1 Ответ

0 голосов
/ 08 октября 2018

Быстрый ответ

declare @table table (name varchar(20),subtitle varchar(20),[date] date )

insert into @table (name,subtitle,date)
values
('ABC','excel','2018-07-07'),
('ABC','excel','2018-08-08'),
('ABC','ppt','2018-09-09'),
('ABC','ppt','2018-10-10'),
('ABC','excel','2018-11-11'),
('ABC','ppt','2018-12-12'),
('DEF','ppt','2018-12-31');

with nums as (

    select *,  
         case when subtitle != lag(subtitle,1) over (partition by name order by date) 
              then 1 
              else 0 end as num
    from @table
)
select *,
    1+sum(num) over (partition by name order by date) AS Group_Number
from nums

Объяснение

То, что вы спрашиваете, не совсем ранжирование.Вы пытаетесь обнаружить "острова" , где имя и субтитры совпадают в последовательностях, упорядоченных строго по дате.

Для этого вы можете сравнить значение текущей строки сПредыдущая.Если они совпадают, вы находитесь на том же «острове».Если нет, есть переключатель.Вы можете использовать это, чтобы выдавать, например, 1 каждый раз, когда обнаруживается изменение.

Вот что:

CASE WHEN subtitle != LAG(subtitle,1) OVER (PARTITION BY name ORDER BY date) 
     THEN 1 

Получив это, вы можете рассчитать количество изменений с помощьюитого:

sum(num) over (partition by name order by date) AS Group_Number

Это будет генерировать значения, начиная с 0. Чтобы получить числа, начинающиеся с 1, просто добавьте 1:

1+sum(num) over (partition by name order by date) AS Group_Number

ОБНОВЛЕНИЕ

Как объясняет Т. Клозен в комментариях, обратное сравнение избавит от +1:

with nums as (

    select *,  
         case when subtitle = lag(subtitle,1) over (partition by name order by date) 
              then 0 
              else 1 end as num
    from @table
)
select *,
    sum(num) over (partition by name order by date) AS Group_Number
from nums

Это также лучший способ обнаружения островов, даже еслиРезультаты в этом случае одинаковы.Первый запрос даст такой результат:

name    subtitle    date    num Group_Number
ABC     excel   2018-07-07  0   1
ABC     excel   2018-08-08  0   1
ABC     ppt     2018-09-09  1   2
ABC     ppt     2018-10-10  0   2
ABC     excel   2018-11-11  1   3
ABC     ppt     2018-12-12  1   4
DEF     ppt     2018-12-31  0   1

Запрос выдает 1 при обнаружении разрыва субтитров , за исключением на границах.

Второй запрос возвращает:

name    subtitle    date    num Group_Number
ABC     excel   2018-07-07  1   1
ABC     excel   2018-08-08  0   1
ABC     ppt     2018-09-09  1   2
ABC     ppt     2018-10-10  0   2
ABC     excel   2018-11-11  1   3
ABC     ppt     2018-12-12  1   4
DEF     ppt     2018-12-31  1   1

В этом случае 1 испускается для каждого изменения, включая границы

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...