当列值更改时,如何将组号添加到 SQL Server 2012 中的顺序记录?
How can I add group numbers to sequential records in SQL Server 2012 when a column value changes?
我一直在使用 SQL Server 2012 中的 window 函数,但无法正常工作,因为我希望避免光标并逐行进行。我的问题是我需要为每条记录添加一个组号。棘手的部分是,每次列值更改时,组号都必须递增,即使它变回记录序列中之前存在的值也是如此。
这是数据示例和我想要的结果:
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
这可以使用 window 函数吗?
一种方法是
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
我一直在使用 SQL Server 2012 中的 window 函数,但无法正常工作,因为我希望避免光标并逐行进行。我的问题是我需要为每条记录添加一个组号。棘手的部分是,每次列值更改时,组号都必须递增,即使它变回记录序列中之前存在的值也是如此。
这是数据示例和我想要的结果:
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
这可以使用 window 函数吗?
一种方法是
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