首页 > 解决方案 > 在 MSSQL 中不使用循环将前一行值与当前行值进行比较

问题描述

源表

行号 旗帜 当前值 Prev_value
1 C V1 无效的
2 V11 无效的
3 V12 无效的
4 C V2 无效的
5 C V31 无效的
6 V32 无效的

我有一个场景,我必须将前一行值与当前行值进行比较,并根据案例条件更新 Curr_value 列,并且应该为表中的所有记录派生 curr_value 和 Prev_value。

用于派生 Curr_value 列的条件是 (Flag='C') then curr_value else Prev_value end 并且我在 MSSQL 中使用 LAG 函数来获取 Previous value 列的情况。

输出

行号 旗帜 当前值 Prev_value
1 C V1 0
2 V1 V1
3 V1 V1
4 C V2 V1
5 C V3 V2
6 V3 V3

我尝试使用 While 循环实现相同的功能,但执行时间非常长。请让我知道是否可以在不使用 MSSQL 循环的情况下实现相同的输出。

标签: sql-serverperformancecompare

解决方案


我将以下脚本设置为一个完整的工作示例:

CREATE TABLE #tmpSampleData(
    Row_no int NOT NULL PRIMARY KEY  
    ,Flag varchar(1) NULL
    ,Curr_value varchar(3) NULL 
); 

INSERT INTO #tmpSampleData (Row_no,Flag,Curr_value) 
VALUES (1, 'C', 'V1')
,(2, 'P', 'V1')
,(3, 'P', 'V1')
,(4, 'C', 'V2')
,(5, 'C', 'V3')
,(6, 'P', 'V3'); 

SELECT 
    sample_data.Row_no
    ,sample_data.Flag
    ,sample_data.Curr_value
    ,LAG(sample_data.Curr_value,1,'0') OVER(ORDER BY sample_data.Row_no) AS Prev_value
    ,CASE 
        WHEN sample_data.Flag = 'C'
            THEN sample_data.Curr_value
        ELSE LAG(sample_data.Curr_value,1,'0') OVER(ORDER BY sample_data.Row_no)
    END AS CalculatedField
FROM 
    #tmpSampleData AS sample_data; 

IF OBJECT_ID(N'tempdb..#tmpSampleData', N'U') IS NOT NULL 
BEGIN 
    DROP TABLE #tmpSampleData; 
END;

但我认为您在这里感兴趣的主要部分就是:

CASE 
    WHEN sample_data.Flag = 'C'
        THEN sample_data.Curr_value
    ELSE LAG(sample_data.Curr_value,1,'0') OVER(ORDER BY sample_data.Row_no)
END AS CalculatedField

只需添加您的条件,sample_data.Flag = 'C'然后返回Curr_value或您的 `LAG 的结果


推荐阅读