Sql 筛选结果行以在时间序列中具有交替状态

Sql 筛选结果行以在时间序列中具有交替状态,sql,sql-server,tsql,datetime,Sql,Sql Server,Tsql,Datetime,使用标准TSQL,我需要的结果是具有交替二进制位状态的行按DATETIME顺序排列,源行按DATETIME顺序排列,但具有冗余状态,这意味着前一行的状态没有变化 源行: State Date 1 2019-06-01 09:00:00.000 0 2019-06-02 00:00:00.000 1 2019-06-02 15:00:00.000 1 2019-06-03 00:00:00.000 - redundant 1 2019

使用标准TSQL,我需要的结果是具有交替二进制位状态的行按DATETIME顺序排列,源行按DATETIME顺序排列,但具有冗余状态,这意味着前一行的状态没有变化

源行:

State   Date
1       2019-06-01 09:00:00.000
0       2019-06-02 00:00:00.000
1       2019-06-02 15:00:00.000
1       2019-06-03 00:00:00.000 - redundant
1       2019-06-03 09:00:00.000 - redundant
1       2019-06-04 09:00:00.000 - redundant
0       2019-06-04 09:15:00.000
1       2019-06-04 09:45:00.000
1       2019-06-05 09:00:00.000 - redundant
0       2019-06-06 09:00:00.000
1       2019-06-07 09:00:00.000
0       2019-06-07 12:15:00.000
在伪SQL中,解决问题的查询如下所示:

SELECT State, Date 
FROM Source_Rows
WHERE State <> (State from previous row)
ORDER BY Date
^状态列交替1-0-1-0-1-0-1

您可以使用滞后功能将当前状态与以前的状态进行比较:

WITH cte AS (
    SELECT *, LAG(State) OVER (ORDER BY Date) AS PrevState
    FROM t
)
SELECT *
FROM cte
WHERE State <> PrevState OR PrevState IS NULL
说明:通过使用记录标识列查找以前的状态值,可以在SQL Server 2005以后的版本中使用此查询

注意:我在select union all脚本中添加了额外的冗余记录。但你还是会得到你期望的结果


搜索前一个值的参考URL:

您的SQL SERVER版本是什么?Microsoft SQL SERVER 2014 SP3-CU1 KB4470220-12.0.6205.1 X64 2018年11月30日02:59:03版权所有c Microsoft Corporation Developer Edition 64位Windows NT 6.3 Build 14393:虚拟机监控程序
WITH cte AS (
    SELECT *, LAG(State) OVER (ORDER BY Date) AS PrevState
    FROM t
)
SELECT *
FROM cte
WHERE State <> PrevState OR PrevState IS NULL
SELECT
    ROW_NUMBER() OVER (ORDER BY x.[Date]) AS RId,
    x.*
    INTO #TblStateDate
FROM
(   
    SELECT 1 AS [State],'2019-06-01 09:00:00.000' AS [Date] UNION ALL
    SELECT 0 AS [State],'2019-06-02 00:00:00.000' AS [Date] UNION ALL
    SELECT 1 AS [State],'2019-06-02 15:00:00.000' AS [Date] UNION ALL
    SELECT 1 AS [State],'2019-06-03 00:00:00.000' AS [Date] UNION ALL
    SELECT 1 AS [State],'2019-06-03 09:00:00.000' AS [Date] UNION ALL
    SELECT 1 AS [State],'2019-06-04 09:00:00.000' AS [Date] UNION ALL
    SELECT 0 AS [State],'2019-06-04 09:15:00.000' AS [Date] UNION ALL
    SELECT 0 AS [State],'2019-06-04 09:30:00.000' AS [Date] UNION ALL --redundant extra added
    SELECT 1 AS [State],'2019-06-04 09:45:00.000' AS [Date] UNION ALL
    SELECT 1 AS [State],'2019-06-05 09:00:00.000' AS [Date] UNION ALL
    SELECT 1 AS [State],'2019-06-05 09:15:00.000' AS [Date] UNION ALL --redundant extra added
    SELECT 1 AS [State],'2019-06-05 09:15:15.000' AS [Date] UNION ALL --redundant extra added
    SELECT 0 AS [State],'2019-06-06 09:00:00.000' AS [Date] UNION ALL
    SELECT 1 AS [State],'2019-06-07 09:00:00.000' AS [Date] UNION ALL
    SELECT 0 AS [State],'2019-06-07 12:15:00.000' AS [Date] UNION ALL --redundant extra added
    SELECT 0 AS [State],'2019-06-07 12:30:00.000' AS [Date] UNION ALL --redundant extra added 
    SELECT 0 AS [State],'2019-06-07 12:45:00.000' AS [Date]           --redundant extra added 
) x

SELECT 
    t1.[State],
    t1.[Date]
FROM #TblStateDate t1
LEFT JOIN #TblStateDate t2 ON t2.RId = t1.RId - 1
WHERE (t1.[State] <> t2.[State] OR t2.[State] IS NULL)

DROP TABLE #TblStateDate;