给予
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 )
db <>提琴here
我正在使用SQL Server 2017。
我所追求的是生成ContinuousId
的能力,它沿着RouteId ASC, Milepoint ASC
行进,当RouteId
或RoadCondition
改变时,它会增加{{1} }
我知道我想使用ContinuousId
,但是处理NULL是我不确定如何解决此问题的部分,因为我不能只是避免合并NULL,因为不能假定两个null设置为相同的值,则当RoadCondition的值为NULL时应递增
答案 0 :(得分:2)
您可以将DENSE_RANK()
与COALESCE()
结合使用:
select e.*,
dense_rank() over (order by RouteId, coalesce(RoadCondition, cast(id as varchar(255)))) AS New_ContinuousId
from @Example e;
答案 1 :(得分:1)
不如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
答案 2 :(得分:0)
以下是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