获取状态更改数据

时间:2019-07-17 11:41:53

标签: sql-server sql-server-2008-r2

Date                           Status            Date_Change 
----------------------------------------------------------------------------
2019-07-10-15.05.46.918680       A               2019-07-10-15.05.46.934000
2019-07-10-15.05.46.918680       A               2019-07-10-15.05.50.272680
2019-07-10-15.05.46.918680       A               2019-07-10-15.05.50.491680  
2019-07-10-15.05.46.918680       B               2019-07-10-15.05.50.740680
2019-07-10-15.05.46.918680       B               2019-07-10-15.05.50.990680
2019-07-10-15.05.46.918680       A               2019-07-15-10.44.54.386680
2019-07-10-15.05.46.918680       A               2019-07-15-10.44.54.837680
2019-07-10-15.05.46.918680       A               2019-07-15-10.45.28.769680

enter image description here

参考上面的数据,我需要状态从A更改为B,C,D等其他日期并再次返回到A的那些Date的数据。

请帮助。我正在使用SQL Server 2008 R2。

我尝试过

select status, min(DATE_CHANGE), max(DATE_CHANGE)
from (select t.*,
             (row_number() over (order by DATE_CHANGE) -
              row_number() over (partition by status order by DATE_CHANGE)
             ) as grp
      from mytable t
     ) t
group by status, grp

但是它不起作用。

输出应类似于:-

Date
-----------------------------
2019-07-10-15.05.46.918680...

如果日期的初始状态为“ A”,然后又更改为其他状态,然后再次返回“ A”,则该日期数据应显示为输出。

1 个答案:

答案 0 :(得分:0)

我想这就是你想要的

CREATE TABLE #data
(
    Date   DATETIME2,                        
    Status   CHAR(1),              
    Date_Change DATETIME2 
);

INSERT INTO #data(Date, Status, Date_Change) 
VALUES
-- positive example - goes from A to B and back to A
('2019-07-10T15:05:46.918680','A','2019-07-10T15:05:46.934000'),
('2019-07-10T15:05:46.918680','A','2019-07-10T15:05:50.272680'),
('2019-07-10T15:05:46.918680','A','2019-07-10T15:05:50.491680'),  
('2019-07-10T15:05:46.918680','B','2019-07-10T15:05:50.740680'),
('2019-07-10T15:05:46.918680','B','2019-07-10T15:05:50.990680'),
('2019-07-10T15:05:46.918680','A','2019-07-15T10:44:54.386680'),
('2019-07-10T15:05:46.918680','A','2019-07-15T10:44:54.837680'),
('2019-07-10T15:05:46.918680','A','2019-07-15T10:45:28.769680'),
-- a second positive example - goes from A to B and back to A
('2019-07-10T15:06:46.918680','A','2019-07-10T15:06:46.934000'),
('2019-07-10T15:06:46.918680','B','2019-07-10T15:06:50.740680'),
('2019-07-10T15:06:46.918680','B','2019-07-10T15:06:50.990680'),
('2019-07-10T15:06:46.918680','A','2019-07-15T11:44:54.386680'),
('2019-07-10T15:06:46.918680','A','2019-07-15T11:44:54.837680'),
('2019-07-10T15:06:46.918680','A','2019-07-15T11:45:28.769680'),
-- negative example 1 - always A
('2019-07-10T15:07:46.918680','A','2019-07-10T15:07:46.934000'),
('2019-07-10T15:07:46.918680','A','2019-07-10T15:07:50.272680'),
('2019-07-10T15:07:46.918680','A','2019-07-10T15:07:50.491680'),  
('2019-07-10T15:07:46.918680','A','2019-07-10T15:07:50.740680'),
-- negative example 2 - goes from A to B but stays there
('2019-07-10T15:08:46.918680','A','2019-07-10T15:08:46.934000'),
('2019-07-10T15:08:46.918680','A','2019-07-10T15:08:50.272680'),
('2019-07-10T15:08:46.918680','A','2019-07-10T15:08:50.491680'),  
('2019-07-10T15:08:46.918680','A','2019-07-10T15:08:50.740680');

-- so I expect 15:05 and 15:06 to be returned, but not 15:07 and 15:08

WITH ranges AS 
(
    SELECT Date, MIN(Date_Change) MinDate, MAX(Date_Change) MaxDate
    FROM #data 
    WHERE Status = 'A'
    GROUP BY Date
)
SELECT DISTINCT #data.Date
FROM #data
INNER JOIN ranges r ON r.Date = #data.Date
WHERE EXISTS (SELECT * FROM #data WHERE Date_Change < MaxDate and Date_Change > MinDate AND Status != 'A')