Сбросить номер строки при изменении значения, но с повторными значениями в разделе - PullRequest
2 голосов
/ 01 мая 2020

У меня возникли проблемы с чем-то очень похожим на этот вопрос T- sql Сброс номера строки при изменении поля

Решение этого вопроса идеально, отлично работает. За исключением случаев, когда я пытаюсь с несколькими другими 'custno', он ломается.

Что я имею в виду под этим:

custno      moddate                     who
--------------------------------------------------
581827      2012-11-08 08:38:00.000     EMSZC14
581827      2012-11-08 08:41:10.000     EMSZC14
581827      2012-11-08 08:53:46.000     EMSZC14
581827      2012-11-08 08:57:04.000     EMSZC14
581827      2012-11-08 08:58:35.000     EMSZC14
581827      2012-11-08 08:59:13.000     EMSZC14
581827      2012-11-08 09:00:06.000     EMSZC14
581827      2012-11-08 09:04:39.000     EMSZC49 Reset row number to 1
581827      2012-11-08 09:05:04.000     EMSZC49
581827      2012-11-08 09:06:32.000     EMSZC49
581827      2012-11-08 09:12:03.000     EMSZC49
581827      2012-11-08 09:12:38.000     EMSZC49
581827      2012-11-08 09:14:18.000     EMSZC49
581827      2012-11-08 09:17:35.000     EMSZC14 Reset row number to 1
-- my new rows for example of problem
581829      2012-11-08 09:12:03.000     EMSZC14 1
581829      2012-11-08 09:12:38.000     EMSZC49 1
581829      2012-11-08 09:14:18.000     EMSZC49
581829      2012-11-08 09:17:35.000     EMSZC14 Reset row number to 1

Внедрение нового custno ломает это решение, которое идеально подходит для одного custno.

with C1 as
(
    select 
        custno, moddate, who,
        lag(who) over(order by moddate) as lag_who
    from 
        chr
),
C2 as
(
    select 
        custno, moddate, who,
        sum(case when who = lag_who then 0 else 1 end) 
            over(order by moddate rows unbounded preceding) as change 
    from 
        C1
)
select 
    row_number() over(partition by change order by moddate) as RowID,
    custno, moddate, who
from 
    C2

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

Мои данные выглядят как

custno   start_date    value

практически одинаково. Я хочу, чтобы строка / ранг равнялась 1 за каждый раз, когда «значение» или «кто» изменяется, независимо от того, было ли это значение / кто был замечен ранее. Это все относительно custno. И я вижу случаи, когда значение / кто может вернуться к тому же значению, а также. Опять же, решение выше обработало это «повторение» просто отлично ... но для одного custno

Я думаю, мне просто нужно каким-то образом добавить какую-то группировку по custno где-нибудь? Просто не уверен, где и как

Спасибо!

1 Ответ

1 голос
/ 01 мая 2020

Это проблема пробелов и островков, и мы можем использовать метод разности номеров строк здесь:

WITH cte AS (
    SELECT *,
        ROW_NUMBER() OVER (PARTITION BY custno ORDER BY moddate) rn1,
        ROW_NUMBER() OVER (PARTITION BY custno, who ORDER BY moddate) rn2
    FROM chr
)

SELECT custno, moddate, who,
    ROW_NUMBER() OVER (PARTITION BY custno, rn1 - rn2 ORDER BY moddate) rn
FROM cte
ORDER BY
    custno,
    moddate;

screen capture of demo below

Демонстрация

Для объяснения разницы в используемом здесь методе нумерации строк, rn1 - это просто упорядоченная по времени последовательность от 1 года на клиента в соответствии с данными Вы показали выше. Последовательность rn2 дополнительно разделена на who. В этом случае разница между rn1 и rn2 всегда будет иметь одинаковое значение для каждого клиента. Именно с этой разницей мы затем берем номер строки по всей таблице, чтобы сгенерировать последовательность, которую вы действительно хотите видеть.

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