2016-10-11 57 views
8

SQL server 2016 ile çalışıyorum ve bu sorguyu nasıl oluşturacağımı anlayamıyorum.SQL Server: satırlar arasındaki tarihleri ​​karşılaştır

en Böyle bir tablo var diyelim: Ben giriş datetime Son seçilen sonuç datetime sonra sadece satırları seçmek istediğiniz

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 

.

Örneğin: 1. satırın sonuç zamanı "2016-05-02 21:50:00" olur, böylece sonraki satır 4. satır olur çünkü bu, giriş süresinin sonuç zamanından sonraki ilk satırıdır. Son seçildi, sonraki satırın satır 4'ün sonuç zamanından sonra olacağını varsayalım. (Sonraki "2016-05-03 03:33:00") böylece bir sonraki satır 5. satır olacaktır.

İstenen sonuç: bunu yapabileceğini

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 
+0

istediğiniz çıktı belirsiz .. daha ayrıntılı olabilirsiniz ... – Teja

+0

Bence sadece bir tek sonuç olduğunu biliyorsunuz –

+0

İlginç ... Kesinlikle WHILE döngüsünde yapılabilir, tek bir SELECT olarak değil, emin olun ... – Anton

cevap

2

bir yolu bir sonraki satır almak için bir özyinelemeli CTE kullanmaktır. Örneğin,

DÜZENLEME: Birden çok "sembol" için, işte çalışacak bir yöntem (örnek verilerle).

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; 
+0

+1, yinelemeli CTE ile nasıl yapılacağını göstermek için +1, her satırda görünen basit bir imleç, kendiliğinden birleşmelerden daha verimli olacaktır. –

+0

Sıfır değere sahip MAXRECURSION belirtilmelidir, değil mi? Varsayılan değer 100'dür. – Anton

+0

Mükemmel yanıt, hızlı ve verimli, 12 numaralı satırda "ID ile siparişi", "Giriş zamanı siparişi" olarak değiştirdim, çünkü ID her zaman giriş zamanında değil. ** Ama başka bir sorunum var **. Bu tabloda 50 farklı sembol var, bu yüzden ilk sembolle çalıştım. 50 sembolün hepsinin üstünde nasıl koşabilirim (her sembol ilk giriş zamanından başlamalıdır) – TVC

1

Bu sorguyu kullanabilirsiniz: Bazen imleç cevap

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 

DÜZENLEME

Ve birden sembol versiyonu olduğunu düşünüyorum

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

Cevabınız için teşekkürler, ancak bu iyi değil. Seçilmese bile tablodaki son sonuç zamanını hesaba katar. – TVC

+0

Örneğin: Bir satırdaki sonuç zamanı 10:00:00 ise ve sonraki satırda giriş saati 9:00:00 ve sonuç zamanı 11:00 ise, o satırı atlamak ve sonuç zamanını kullanmamak için varsayalım. çünkü giriş zamanı son sonuç saatinden önce. Cevabınız şimdi 11: 00'dan sonra sonraki giriş saatini ve – TVC

1

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 
+0

'u varsaydığı gibi 10: 00'dan sonra aramayacaktır. Bu işlevi nasıl çalıştırabilirim? – TVC

+0

SELECT * FROM getSelected() –

+0

Çok güzel, Tekli Sembol için mükemmel çalışır, Ama birden çok sembol için sahip olduğum başka bir sorun ekliyorum, ZLK'nın yanıtladığı yoruma bakın. Her birinin baştan başlayacağı birden fazla Simge için nasıl yapabilirim? – TVC