如何通过特定的顺序检测更改值

问题描述 投票:3回答:3

特定

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行驶时和在RouteIdRoadCondition变化,它增加ContinuousId

我知道我需要使用LEAD()但处理空值是部分我不知道如何来解决这个问题,因为我不能只是聚结NULL值,因为没有两个零点可以认为是相同的值,它应该增量每当它看到一个空的RoadCondition

sql sql-server tsql
3个回答
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
投票

不聪明的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

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
© www.soinside.com 2019 - 2024. All rights reserved.