当列值更改时,如何将组号添加到 SQL Server 2012 中的顺序记录?

Posted

技术标签:

【中文标题】当列值更改时,如何将组号添加到 SQL Server 2012 中的顺序记录?【英文标题】:How can I add group numbers to sequential records in SQL Server 2012 when a column value changes? 【发布时间】:2017-01-12 18:15:02 【问题描述】:

我一直在使用 SQL Server 2012 中的窗口函数,但无法让它工作,因为我希望避免使用游标并逐行进行。我的问题是我需要为每条记录添加一个组号。棘手的部分是,每次列值更改时,组编号都必须增加,即使它变回记录序列中之前存在的值。

以下是数据示例和我想要的结果:

if object_id('tempdb..#data') is not null 
    drop table #data

create table #data
(
    id int identity(1,1)
    ,mytime datetime
    ,distance int
    ,direction varchar(20)
)

insert into #data (mytime, distance, direction) 
values 
 ('2016-01-01 08:00',10,'North')
,('2016-01-01 08:30',18,'North')
,('2016-01-01 09:00',15,'North')
,('2016-01-01 09:30',12,'South')
,('2016-01-01 10:00',16,'South')
,('2016-01-01 10:30',45,'North')
,('2016-01-01 11:00',23,'North')
,('2016-01-01 11:30',14,'South')
,('2016-01-01 12:00',40,'South')

期望的结果:

mytime              Distance    Direction   GroupNumber
--------------------------------------------------------
2016-01-01 8:00     10          North       1
2016-01-01 8:30     18          North       1
2016-01-01 9:00     15          North       1
2016-01-01 9:30     12          South       2
2016-01-01 10:00    16          South       2
2016-01-01 10:30    45          North       3
2016-01-01 11:00    23          North       3
2016-01-01 11:30    14          South       4
2016-01-01 12:00    40          South       4

这可以使用窗口函数吗?

【问题讨论】:

【参考方案1】:

一种方法是

WITH T
     AS (SELECT *,
                CASE
                  WHEN LAG(direction)
                         OVER (ORDER BY ID) = direction THEN 0
                  ELSE 1
                END AS Flag
         FROM   #data)
SELECT mytime,
       Distance,
       Direction,
       SUM(Flag) OVER (ORDER BY id) AS GroupNumber
FROM   T 

以上假设Direction 不包含任何NULLs。如果可能的话,它需要一个小的调整。但是您还需要定义两个连续的NULL 是否应该被视为相等(假设是这种情况,那么下面的变体将起作用)

WITH T
     AS (SELECT *,
                prev = LAG(direction) OVER (ORDER BY ID),
                rn = ROW_NUMBER() OVER (ORDER BY ID)
         FROM   #data)
SELECT mytime,
       Distance,
       Direction,
       SUM(CASE WHEN rn > 1 AND EXISTS(SELECT prev 
                                       INTERSECT 
                                       SELECT Direction) THEN 0 ELSE 1 END) OVER (ORDER BY id) AS GroupNumber
FROM   T 
ORDER BY ID

【讨论】:

那真是太好了。 这很棒。我想我的方向字段有一些 NULL 或空白值,但可能会将它们过滤掉。

以上是关于当列值更改时,如何将组号添加到 SQL Server 2012 中的顺序记录?的主要内容,如果未能解决你的问题,请参考以下文章

当列值匹配时,Pandas Dataframe 从一行中替换 Nan

当列值是 84 字节文本字段时,postgres 中保持列唯一的最有效方法是啥?

Hive : 当列值由分隔符 (~) 分隔时,将单个记录扩展为多个记录

SQL Pivot表较大的列值给出了太长的错误

如何将组字段添加到自定义用户?

ORA-00904: 无效的标识符,当列标题正确时