特定
Id | RouteId | Milepoint | RoadCondition -: | :------ | --------: | :------------ 1 | A | 0 | X 2 | A | 1 | X 3 | A | 4 | Y 4 | B | 0 | Y 5 | B | 2 | null 6 | B | 5 | null 7 | B | 6 | Z 8 | B | 18 | Z 9 | C | 0 | X
我终究
Id | RouteId | Milepoint | RoadCondition | ContinuousId -: | :------ | --------: | :------------ | -----------: 1 | A | 0 | X | 1 2 | A | 1 | X | 1 3 | A | 4 | Y | 2 4 | B | 0 | Y | 3 5 | B | 2 | null | 4 6 | B | 5 | null | 5 7 | B | 6 | Z | 6 8 | B | 18 | Z | 6 9 | C | 0 | X | 7
DECLARE @Example TABLE ( Id INT primary key, RouteId varchar(50), Milepoint INT, RoadCondition varchar(50), ContinuousId INT )
分贝<>小提琴here
我使用SQL服务器2017年。
我所追求的是产生ContinuousId
的能力,沿着RouteId ASC, Milepoint ASC
行驶时和在RouteId
或RoadCondition
变化,它增加ContinuousId
我知道我需要使用LEAD()
但处理空值是部分我不知道如何来解决这个问题,因为我不能只是聚结NULL值,因为没有两个零点可以认为是相同的值,它应该增量每当它看到一个空的RoadCondition
您可以使用DENSE_RANK()
与COALESCE()
:
select e.*,
dense_rank() over (order by RouteId, coalesce(RoadCondition, cast(id as varchar(255)))) AS New_ContinuousId
from @Example e;
不聪明的DENSE_RANK,但我想这样的作品,以及
DECLARE @Example TABLE (
Id INT primary key,
RouteId varchar(50),
Milepoint INT,
RoadCondition varchar(50)
)
INSERT INTO @Example
VALUES
(1, 'A', 0, 'X')
,(2, 'A', 1, 'X')
,(3, 'A', 4, 'Y')
,(4, 'B', 0, 'Y')
,(5, 'B', 2, NULL)
,(6, 'B', 5, NULL)
,(7, 'B', 6, 'Z')
,(8, 'B', 18, 'Z')
,(9, 'C', 0, 'X')
;WITH CTE AS(
SELECT *
,CASE
WHEN
RouteId = LAG(RouteId) OVER (PARTITION BY RouteId ORDER BY Milepoint)
AND
RoadCondition = LAG(RoadCondition) OVER (PARTITION BY RouteId ORDER BY Milepoint)
THEN 0
ELSE 1
END AS StartOfNextIsland
FROM @Example
)
SELECT *, SUM(StartOfNextIsland) OVER (ORDER BY RouteId, Milepoint) AS ContinuousId
FROM CTE
以下是CTE的
;with cte as (
select *,1 [New_ContinuousId] from @Example e where Id=1
union all
select e.*
,cte.New_ContinuousId+(case when
e.RouteId is null
or e.RoadCondition is null
or cte.RoadCondition is null
or cte.RouteId is null
or e.RouteId<>cte.RouteId
or e.RoadCondition<>cte.RoadCondition
then 1 else 0 end) [ccc] from @Example e
inner join cte on cte.Id+1=e.Id
)
select * from cte
结果:
Id RouteId Milepoint RoadCondition ContinuousId New_ContinuousId
== ======= ========= ============= ============ =================
1 A 0 X 1 1
2 A 1 X 1 1
3 A 4 Y 2 2
4 B 0 Y 3 3
5 B 2 NULL 4 4
6 B 5 NULL 5 5
7 B 6 Z 6 6
8 B 18 Z 6 6
9 C 0 X 7 7
下面是一个较短的版本与LAG,给相同的结果如上述。
;with cte as (
select * ,case when LAG(RoadCondition+RouteId,1) over (order by Id)=RoadCondition+RouteId then null else 1 end [cc]
from @Example e
)
select Id,RouteId,Milepoint,RoadCondition,ContinuousId,count(cc) over (order by Id) [New_ContinuousId] from cte