我需要有关SQL逻辑/语言的一些建议。我有一个游标,它将在一个表中循环浏览year + customer_id + order_no
的数千种组合。
数据样本
year customer_id order_no markerA markerB markerC MarkerD
2018 32329 523142
2018 32329 523243
2018 39566 523508
2018 42352 523214
2017 17675 470537
2017 21486 479414
2017 39566 479038
2017 42352 479220
以此类推
我需要做的是说将组合的值拉到customer_id + year + order_no之上
如果再也没有出现customer_no(在初始拉动之后),则MarkerA - 'Y'.
但是如果customer_no再次出现-如果该年份与初始拉动相同,则MarkerB -'Y'.
但是,如果customer_no再次出现-但是年份不同,如果年份是1,则进一步检查MarkerC -'Y'.
但是如果customer_no再次出现-但是年份不同,如果年份不是Year-1,则在其他地方存在第2年或更大年份的行确实存在,则MarkerD -'Y'.
declare @order_year int
declare @customer_id int
declare @order_dt datetime
declare @order_no int
BEGIN
DECLARE db_cursor CURSOR FOR
Select distinct year, customer_id, order_dt, order_no From #Compare_Data
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO @order_year, @customer_no, @order_dt, @order_no
WHILE @@FETCH_STATUS = 0
BEGIN
...我知道我需要一系列的IF语句,但是我不确定如果存在的话如何比较。无法确定某个值是否存在,因为您当然只是从表中拉出了customer_no / season等,所以肯定存在一个值。我如何说是否存在一个值,但不包括我正在查看的值。
FETCH NEXT FROM db_cursor INTO @customer_no, @order_dt, @order_no
END
CLOSE db_cursor
DEALLOCATE db_cursor
END
答案 0 :(得分:2)
如果我正确理解了您的问题,那么您将按照降序检查客户订单,以确认订单状态是否与该客户的最新订单相比较。
老实说,我有点不明白我是否了解您的要求,因此我的解决方案将为您提供所需要做的要点。
首先不要使用光标。很少有合理的理由使用它们,它们速度慢且价格昂贵。相反,应使用窗口函数解决此问题。
窗口函数使您可以通过在分区上执行聚合函数来从某一行查看结果集的窗口。因此,例如,如果您希望所有具有相同客户ID的行的最小年份,请输入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
案例陈述的工作方式如下:
我注释了派生列DescOrderIdx
,因为尽管我的解决方案不需要它,但可能需要它以满足您的确切要求。如果不标记第一个订单,则应使用该值是否不等于1(最新的订单索引)作为附加条件。