簡體   English   中英

SQL Server:比較行之間的日期

[英]SQL Server : compare dates between rows

我正在使用SQL Server 2016,但無法弄清楚如何構建該查詢。

假設我有一個這樣的表:

ID  EntryTime               ResultTime
1   2016-05-02 13:30:00     2016-05-02 21:50:00
2   2016-05-02 14:45:00     2016-05-02 22:00:00
3   2016-05-02 16:30:00     2016-05-02 22:21:00
4   2016-05-03 01:00:00     2016-05-03 03:33:00
5   2016-05-03 10:30:00     2016-05-04 07:47:00
6   2016-05-03 12:30:00     2016-05-03 22:45:00
7   2016-05-04 11:30:00     2016-05-05 21:30:00
8   2016-05-04 12:30:00     2016-05-04 22:58:00
9   2016-05-04 13:30:00     2016-05-04 23:04:00
10  2016-05-04 13:45:00     2016-05-04 22:59:00
11  2016-05-04 14:00:00     2016-05-04 22:59:00
12  2016-05-04 14:15:00     2016-05-04 23:04:00
13  2016-05-04 17:45:00     2016-05-04 21:47:00
14  2016-05-05 23:30:00     2016-05-06 03:25:00
15  2016-05-05 23:45:00     2016-05-06 03:30:00
16  2016-05-06 00:00:00     2016-05-06 03:32:00
17  2016-05-06 00:15:00     2016-05-06 03:31:00
18  2016-05-06 00:30:00     2016-05-06 03:25:00
19  2016-05-06 00:45:00     2016-05-06 02:50:00
20  2016-05-06 01:00:00     2016-05-06 03:25:00

我只想選擇條目datetime在最后選擇的結果datetime之后的行。

例如:第1行的結果時間是“ 2016-05-02 21:50:00”,因此下一行將是第4行,因為這是輸入時間在上次選擇的結果時間之后的第一行,下一行應該在第4行的結果時間之后(“ 2016-05-03 03:33:00”之后),因此下一行將是第5行。

請求的結果是:

ID  EntryTime               ResultTime
1   2016-05-02 13:30:00     2016-05-02 21:50:00
4   2016-05-03 01:00:00     2016-05-03 03:33:00
5   2016-05-03 10:30:00     2016-05-04 07:47:00
7   2016-05-04 11:30:00     2016-05-05 21:30:00
14  2016-05-05 23:30:00     2016-05-06 03:25:00

一種方法是使用遞歸CTE獲取下一行。 例如,

with cte as (
    select *
    from myTable
    where id = 1
    union all
    select t.*
    from myTable t
    cross join cte
    where t.id = (
        select id 
        from (
            select id, row_number() over (order by id) rn 
            from myTable 
            where entrytime > cte.resulttime) z 
        where rn = 1)
    )
select * from cte;

編輯:對於多個“符號”,這是一種可以工作的方法(帶有示例數據)。

DECLARE @myTable TABLE (Symbol CHAR(3), EntryTime DATETIME, ResultTime DATETIME)
INSERT @myTable VALUES ('AAA','2016-05-02 13:30:00','2016-05-02 21:50:00')
,('AAA','2016-05-02 14:45:00','2016-05-02 22:00:00')
,('AAA','2016-05-02 16:30:00','2016-05-02 22:21:00')
,('AAA','2016-05-03 01:00:00','2016-05-03 03:33:00')
,('AAA','2016-05-03 10:30:00','2016-05-04 07:47:00')
,('AAA','2016-05-03 12:30:00','2016-05-03 22:45:00')
,('AAA','2016-05-04 11:30:00','2016-05-05 21:30:00')
,('AAA','2016-05-04 12:30:00','2016-05-04 22:58:00')
,('AAA','2016-05-04 13:30:00','2016-05-04 23:04:00')
,('AAA','2016-05-04 13:45:00','2016-05-04 22:59:00')
,('AAA','2016-05-04 14:00:00','2016-05-04 22:59:00')
,('AAA','2016-05-04 14:15:00','2016-05-04 23:04:00')
,('AAA','2016-05-04 17:45:00','2016-05-04 21:47:00')
,('AAA','2016-05-05 23:30:00','2016-05-06 03:25:00')
,('AAA','2016-05-05 23:45:00','2016-05-06 03:30:00')
,('AAA','2016-05-06 00:00:00','2016-05-06 03:32:00')
,('AAA','2016-05-06 00:15:00','2016-05-06 03:31:00')
,('AAA','2016-05-06 00:30:00','2016-05-06 03:25:00')
,('AAA','2016-05-06 00:45:00','2016-05-06 02:50:00')
,('AAA','2016-05-06 01:00:00','2016-05-06 03:25:00')
,('BBB','2016-05-02 01:00:00','2016-05-02 03:01:00')
,('BBB','2016-05-02 02:00:00','2016-05-02 03:05:00')
,('BBB','2016-05-02 03:00:00','2016-05-02 03:40:00')
,('BBB','2016-05-02 04:00:00','2016-05-02 04:01:00')
,('BBB','2016-05-02 05:00:00','2016-05-03 07:00:00')
,('BBB','2016-05-02 06:00:00','2016-05-02 07:00:00')
,('BBB','2016-05-03 06:00:00','2016-05-03 07:05:00')
,('BBB','2016-05-04 06:01:00','2016-05-04 07:08:00')
,('BBB','2016-05-04 06:07:00','2016-05-04 07:52:00')
,('BBB','2016-05-05 06:00:00','2016-05-05 07:49:00')
,('CCC','2016-05-05 06:00:00','2016-05-05 07:04:00')
,('CCC','2016-05-05 06:05:00','2016-05-05 06:55:00')
,('CCC','2016-05-05 07:00:00','2016-05-05 07:10:00')
,('CCC','2016-05-05 07:06:00','2016-05-05 08:05:00')
,('CCC','2016-05-05 08:00:00','2016-05-05 08:15:00')
,('CCC','2016-05-05 08:09:00','2016-05-05 09:00:00');

WITH myTable AS (
    SELECT Symbol, EntryTime, ResultTime, ROW_NUMBER() OVER (PARTITION BY Symbol ORDER BY EntryTime) RN
    FROM @myTable)
, CTE AS (
    SELECT *
    FROM myTable
    WHERE RN = 1
    UNION ALL
    SELECT T.*
    FROM CTE
    CROSS APPLY (
        SELECT Symbol, EntryTime, ResultTime, RN
        FROM (
            SELECT *, ROW_NUMBER() OVER (ORDER BY EntryTime) RN2
            FROM myTable
            WHERE Symbol = CTE.Symbol
            AND EntryTime > CTE.ResultTime) Z
        WHERE RN2 = 1) T
    )
SELECT Symbol, EntryTime, ResultTime--, RN [ID?]
FROM CTE
ORDER BY Symbol;

您可以使用以下查詢:

select *
from @t t1
where not exists (
    select 1
    from @t t2
    where t2.id < t1.id and t2.resultDate > t1.entryDate
)

我認為有時候游標是答案

CREATE FUNCTION getSelected
(    
)
RETURNS @res TABLE 
(
    id int, EntryTime DATETIME, ResultTime DATETIME
)
AS
BEGIN
    declare @idC int;
    declare @ResultTimeC DATETIME;
    declare @EntryTimeC DATETIME;
    declare @lastNextDate DATETIME;

    DECLARE Iterator CURSOR LOCAL FAST_FORWARD 
    FOR SELECT id, EntryTime, ResultTime FROM dbo.tt1 order by EntryTime, id
    OPEN Iterator
    WHILE 1=1 BEGIN
        FETCH NEXT FROM Iterator INTO @idC, @EntryTimeC, @ResultTimeC
        IF @@FETCH_STATUS < 0 BREAK 

        if(@lastNextDate is null or @lastNextDate < @EntryTimeC) begin
            set @lastNextDate = @ResultTimeC;
            insert into @res (id, EntryTime, ResultTime) values (@idC, @EntryTimeC, @ResultTimeC);
        end;            
    END
    CLOSE Iterator
    DEALLOCATE Iterator;

    RETURN 
END

編輯

和多符號版本

CREATE FUNCTION getSelected2
(    
)
RETURNS @res TABLE 
(
    id int, EntryTime DATETIME, ResultTime DATETIME, Symbol char(3)
)
AS
BEGIN
    declare @idC int;
    declare @ResultTimeC DATETIME;
    declare @EntryTimeC DATETIME;
    declare @SymbolC char(3);
    declare @lastNextDate DATETIME; 
    declare @lastSymbol char(3);

    DECLARE Iterator CURSOR FAST_FORWARD 
    FOR SELECT id, EntryTime, ResultTime, Symbol FROM dbo.tt2 order by Symbol, EntryTime, id
    OPEN Iterator
    WHILE 1=1 BEGIN
        FETCH NEXT FROM Iterator INTO @idC, @EntryTimeC, @ResultTimeC, @SymbolC
        IF @@FETCH_STATUS < 0 BREAK 

        if(@lastSymbol is null or @lastSymbol <> @SymbolC) begin
            set @lastSymbol = @SymbolC;
            set @lastNextDate = null;
        end;
        if(@lastNextDate is null or @lastNextDate < @EntryTimeC) begin
            set @lastNextDate = @ResultTimeC;
            insert into @res (id, EntryTime, ResultTime, Symbol) values (@idC, @EntryTimeC, @ResultTimeC, @SymbolC);
        end;            
    END
    CLOSE Iterator
    DEALLOCATE Iterator;

    RETURN 
END

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM