Если я правильно понимаю вашу проблему, вы проверяете заказы клиентов в порядке убывания, который вы пошли, чтобы определить состояние заказов в сравнении с последним заказом для клиента.
Честно говоря, я немного сомневаюсь, понимаю ли я ваши требования, поэтому мое решение должно дать вам суть того, что вам нужно сделать.
Во-первых, не используйте пользовательские курсоры.Редко есть законная причина их использования, они медленные и дорогие.Вместо этого эту проблему следует решить с помощью оконных функций.
Оконные функции позволяют вам смотреть в окно вашего результирующего набора из определенной строки, выполняя агрегатную функцию над разделом.Например, если вы хотите указать минимальный год для всех строк с одинаковым идентификатором клиента, напишите MIN([Year]) OVER (PARTITION BY CustomerId)
.
Ниже приведена попытка решить вашу проблему.Я мог бы предположить, что вам придется настроить выражения CASE
в соответствии с вашими точными критериями.
-- Setup test data
DECLARE @CompareData TABLE ( [Year] INT, CustomerId INT, OrderNo INT );
INSERT INTO @CompareData
VALUES
(2018, 32329, 523142),
(2018, 32329, 523243),
(2018, 39566, 523508),
(2018, 42352, 523214),
(2017, 17675, 470537),
(2017, 21486, 479414),
(2017, 39566, 479038),
(2017, 42352, 479220),
(2016, 42352, 479220);
-- solution
WITH src AS (
SELECT *
--, ROW_NUMBER() OVER
-- (PARTITION BY CustomerId ORDER BY Year DESC, OrderNo DESC) DescOrderIdx
, COUNT(CustomerId) OVER (PARTITION BY CustomerId) CustCount
, MIN([Year]) OVER (PARTITION BY CustomerId) MinYear
, MAX([Year]) OVER (PARTITION BY CUstomerId) MaxYear
FROM @CompareData
)
SELECT [Year], CustomerId, OrderNo
, CASE WHEN CustCount = 1 THEN 'Y' ELSE '' END [MarkerA]
, CASE WHEN CustCount > 1 AND [Year] = MaxYear THEN 'Y' ELSE '' END [MarkerB]
, CASE WHEN CustCount > 1 AND [Year] = MaxYear - 1 THEN 'Y' ELSE '' END [MarkerC]
, CASE WHEN CustCount > 1 AND [Year] < MaxYear - 1 THEN 'Y' ELSE '' END [MarkerD]
FROM src
Вот как работают операторы case:
- Будет толькобудет истинно, если существует только одна запись о клиенте
- Будет истинно, если существует несколько записей о клиентах, но год равен максимальному году
- Будет истинно, если существует несколько записей о клиентах, но год равен максимальному году- 1
- Будет истинно, если существует несколько записей о клиентах, но год меньше максимального года - 1.
Я закомментировал производный столбец DescOrderIdx
, потому что пока его нетМне нужно мое решение, возможно, оно будет соответствовать вашим точным требованиям.Если первый ордер не должен быть помечен, то в качестве дополнительных критериев следует использовать проверку, если это значение не равно 1 (самый последний индекс ордера).