[MSSQL]SQL疑难杂症实战记录-巧妙利用PARTITION分组排名递增特性解决合并连续相同数据行

问题提出

先造一些测试数据以说明题目:html

DECLARE @TestData TABLE(ID INT,Col1 VARCHAR(20),Col2 VARCHAR(20))
INSERT INTO @TestData(ID,Col1,Col2)
SELECT 1,'New','Approved' UNION ALL
SELECT 2,'Approved','Commited' UNION ALL
SELECT 3,'Commited','In Progress' UNION ALL
SELECT 4,'New','Approved' UNION ALL
SELECT 5,'New','Approved' UNION ALL
SELECT 6,'New','Approved' UNION ALL
SELECT 7,'Approved','Removed'
SELECT * FROM @TestData函数

image

image

 

数听说明,ID列连续自增,列1和列2都是TFS中PBI的状态记录,就是从什么变动到什么,如新建到批准,批准到提交神马的测试

如今要求连续且相同的状态变动记录合并,不连续或者不一样的状态变动保留,例如:3d

以上图为例,ID为1,4,5,6的记录都是从NewApproved状态,可是记录1与记录四、五、6不相邻,或者说不连续,那么就要分红两组,htm

记录1一组,记录四、五、6一组,其它记录由于状态变动不相同因此所有保留,最后的查询结果应该长成下图这个样子:blog

image

继续以前你能够先本身试下,这可能会带来新的解题思路,get

 

解题思路

该问题的关键在于GROUP BY会把记录一、四、五、6合并在一块儿,而这不符合要求,仅须要合并四、五、6,源表里没有这样一个字段能够将记录1与记录四、五、6区分开来,这是解题的关键it

这里能够利用RANK函数配合使用PARTITION关键字,首先把1456分到一组去,同时产生一个组内排名的新字段R,这个排名R很关键,后边会用到,见下图:im

image

RANK函数不了解的点这里d3

RANK函数以Col1 + Col2为分组条件,这样分红了四组,分别是New-Approved、Approved-Commited、Commited-In Progress、Approved-Removed

在New-Approved组内,记录一、四、五、6分别排名一、二、三、4;其它组内仅一条记录,在其组内排名均为1

如今制造了一个R字段,R字段标识了每条记录在其组内的排名,排名自1开始递增,

源表内ID自增,组内排名R递增,这就是解题的关键,

当连续相同的记录出现时,其ID与其排名R在同时递增,则其差值是相同的,拿到这个差值就能够很容易解决题目了,看下图:

image

记录四、五、6相同且连续出现,其ID与其排名在同时增加,其差值则保持不变,这里使用Col1 + Col2 + Gap做为分组条件便可将记录四、五、6合并,再取个最小ID出来,问题解决,完整脚本以下:

image

但是若是ID不连续时怎么办呢?这个不难,参考[MSSQL]ROW_NUMBER函数

相关文章
相关标签/搜索