SQL Server Подсчитывает последовательные предыдущие строки на основе значений

#sql #sql-server #sql-server-2012

#sql #sql-server #sql-server-2012

Вопрос:

Мне сложно сформулировать этот вопрос.

У меня есть таблица, как показано ниже:

Дата ItemNumber FlagA ФлагB
2020-01-01 101 Y N
2020-01-02 101 N N
2020-01-03 101 Y N
2020-01-04 101 Y N
2020-01-05 101 Y Y
2020-01-01 102 Y N
2020-01-02 102 N N
2020-01-03 102 N N
2020-01-04 102 Y Y

Моя цель — подсчитать последовательные даты, где FlagA = Y, включая и предшествующие дате, где flagB = Y для каждого ItemNumber . Последняя дата для каждого ItemNumber в таблице всегда будет иметь flagB = Y.

Я пытаюсь добиться этого, добавив дополнительный столбец:

Дата ItemNumber FlagA ФлагB RunningCount
2020-01-01 101 Y N 0
2020-01-02 101 N N 0
2020-01-03 101 Y N 1
2020-01-04 101 Y N 2
2020-01-05 101 Y Y 3
2020-01-01 102 Y N 0
2020-01-02 102 N N 0
2020-01-03 102 N N 0
2020-01-04 102 Y Y 1

Я работаю на SQL Server 2012, но не имею большого опыта работы с оконными функциями. Я пробовал несколько вещей, в том числе:

 COUNT(CASE WHEN [FLagB] = 'Y' THEN 1 ELSE 0 END) 
              over (partition by [ItemNumber],[FlagB] 
                   order by [Date] ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS [RunningCount]
 

и:

 COUNT(CASE WHEN [FLagB] = 'Y' THEN [ItemNumber] END) 
              over (PARTITION BY [ItemNumber] 
                   order by [Date] ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS [RunningCount]
 

но они не получили правильных результатов.

Возможно, есть лучший способ сделать это — мне не нужно добавлять новый столбец в таблицу, мне нужен только запрос, который предоставляет количество для каждого ItemNumber .

Любые советы будут с благодарностью приняты. Заранее благодарю вас.

Ответ №1:

Похоже, вам нужно перечисление flagA = Y для самой последней непрерывной последовательности. Это было бы:

 select t.*,
       (case when grp = 0 and flagA = 'Y'
             then row_number() over (partition by grp, flagA order by date) 
             else 0
        end) as runningCount
from (select t.*,
             sum(case when flagA = 'N' then 1 else 0 end) over (partition by itemNumber order by date desc) as grp
      from t
     ) t;
 

Комментарии:

1. Спасибо за ответ, к сожалению, у меня это не сработало. При попытке присвоить псевдоним части инструкции case как ‘seqnum’ выдается ошибка. Удаление этого добавляет счетчик, начинающийся с 1 для первой даты первого номера элемента по последнюю дату, затем возвращает 0 для остальных номеров элементов и дат.

2. @sprVUHL . , , я удалил это.