如果存在于同一个 SQL 表中,则游标更新



我需要一些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 + 年 + order_no

如果没有customer_no再次出现(在初始拉取之后(,则MarkerA - 'Y'.

但是,如果customer_no再次出现 - 如果该年份相同,则在初始拉动中,则MarkerB -'Y'.

但是,如果customer_no再次出现 - 但年份不同,如果年份是年份 - 1 则MarkerC -'Y'.

但是,如果customer_no再次出现 - 但如果年份不是年份 - 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/季节等。我怎么说是否存在一个值,不包括我正在查看的值。

FETCH NEXT FROM db_cursor INTO @customer_no, @order_dt, @order_no
END 
CLOSE db_cursor  
DEALLOCATE db_cursor
END

如果我正确理解您的问题,您正在按降序检查客户订单,以确定订单状态与客户的最新订单进行比较。

老实说,如果我了解您的要求,我有点生气,所以我的解决方案应该会为您提供您需要做什么的要点。

首先不要使用游标。 很少有合法的理由使用它们,它们既慢又昂贵。 这个问题应该用窗口函数来解决。

窗口函数允许您通过对分区执行聚合函数来查看特定行的结果集的窗口。 因此,例如,如果您希望具有相同客户 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

以下是案例陈述的工作原理:

  1. 当仅存在一条客户记录时才为真
  2. 如果存在多个客户记录,则为 true,但年份等于最大年份
  3. 如果存在多个客户记录,但年份等于最大年份 - 1,则为 true
  4. 如果存在多个客户记录,但年份小于最大年份 - 1,则为 true。

我注释掉了派生列DescOrderIdx因为虽然我的解决方案中不需要它,但可能需要它来满足您的确切要求。 如果不标记第一个订单,则应将检查该值是否不等于 1(最新的订单索引(用作附加条件。

最新更新