SQL 服务器 - 选择未更改数据的时间段

SQL Server - Selecting periods without changes in data

我想要做的是 select 时间段,其中 table 中的其余数据是 stable 基于一列并检查是否有变化在此期间的第二列值中。

Table:

create table #stable_periods
(
[Date]             date,
[Car_Reg]          nvarchar(10),
[Internal_Damages] int,
[External_Damages] int
)

insert into #stable_periods
values  ('2015-08-19', 'ABC123', 10, 10),
        ('2015-08-18', 'ABC123', 9, 10),
        ('2015-08-17', 'ABC123', 8, 9),
        ('2015-08-16', 'ABC123', 9, 9),
        ('2015-08-15', 'ABC123', 10, 10),
        ('2015-08-14', 'ABC123', 10, 10),
        ('2015-08-19', 'ABC456', 5, 3),
        ('2015-08-18', 'ABC456', 5, 4),
        ('2015-08-17', 'ABC456', 8, 4),
        ('2015-08-16', 'ABC456', 9, 4),
        ('2015-08-15', 'ABC456', 10, 10),
        ('2015-01-01', 'ABC123', 1, 1),
        ('2015-01-01', 'ABC456', NULL, NULL);

--select * from #stable_periods
-- Unfortunately I can’t post pictures yet but you get the point of how the table looks like

我想收到的是

Car_Reg   FromDate ToDate           External_Damages    Have internal damages changed in this period?
ABC123   2015-08-18 2015-08-19   10               Yes
ABC123   2015-08-16 2015-08-17   9               Yes
ABC123   2015-08-14 2015-08-15   10               No
ABC123   2015-01-01 2015-01-01   1               No
ABC456   2015-08-19 2015-08-19   3               No
ABC456   2015-08-16 2015-08-18   4               Yes
ABC456   2015-08-15 2015-08-15   10               No
ABC456   2015-01-01 2015-01-01   NULL               NULL

基本上是建立 [External_Damages] 不变的周期框架,并检查 [Internal_Damages] 是否在同一时期内发生变化(无论多少次)。 我花了很多时间尝试,但我担心我的抽象思维水平太低了…… 很高兴看到任何建议。

谢谢,

巴尔托斯

我认为这是 Islands Problem 的一种形式。

这是使用 ROW_NUMBERGROUP BY 的解决方案:

SQL Fiddle

WITH CTE AS(
    SELECT *,
        RN = DATEADD(DAY, - ROW_NUMBER() OVER(PARTITION BY Car_reg, External_Damages ORDER BY [Date]), [Date])
    FROM #stable_periods
)
SELECT
    Car_Reg,
    FromDate = MIN([Date]),
    ToDate = MAX([Date]) ,
    External_Damages,
    Change =
            CASE 
                WHEN MAX(External_Damages) IS NULL THEN NULL
                WHEN COUNT(DISTINCT Internal_Damages) > 1 THEN 'Yes' 
                ELSE 'No' 
            END     
FROM CTE c
GROUP BY Car_Reg, External_Damages, RN
ORDER BY Car_Reg, ToDate DESC