sql-server - 在 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 循环的情况下实现相同的输出。
解决方案
我将以下脚本设置为一个完整的工作示例:
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 的结果
推荐阅读
- ios - 是否可以在 UICollectionView 下有一个 UITableView?
- .net - 无论使用 TLS 1.1 的 .net 代码如何,都使用 TLS 1.2
- java - 如何按嵌套地图值对外部地图进行排序
- javascript - Vue.js:v-for 循环中的值未与正确的数组项保持一致
- javascript - AJAX 上传脚本未捕获引用错误应用未定义
- python - 如何在亚马逊 lambda 上使用 python 将 csv 转换为 json?
- php - 将来自 php laravel 的远程数据绑定到 Angular 前端
- android - 微调器 OnTouchListener
- ios - 更改 textField 时从其他视图控制器更改变量
- django - 我如何按标签名称搜索帖子是否已发布