2015-03-30 16 views
5

Esiste una funzione per controllare la data continua. Sto avendo problemi a lavorare con questo problema di seguito:Come selezionare la data continua in sql

mia tabella ha una colonna datetime con i seguenti dati:

---------- 
2015-03-11 
2015-03-12 
2015-03-13 
2015-03-16 

data di inizio Data come 2015-3-11 e di fine come 2015-3-17. Voglio il risultato come:

---------- 
2015-03-11 
2015-03-12 
2015-03-13 

Qualcuno può suggerire qualcosa?

+0

Qual è il tipo del vostro campo? –

+0

Ho appena modificato la mia domanda alla fine. ora puoi vedere che non posso applicare l'opzione in o tra adesso. –

+0

Cosa succede se non ci sono '2015-03-11' nei dati? E un giorno salta, ma le prossime due o tre date sono continue? –

risposta

5

Sto pensando che si tratti di una variante del problema Grouping Islands of Contiguous Dates. Questo può essere fatto utilizzando ROW_NUMBER():

SQL Fiddle

CREATE TABLE Test(
    tDate DATETIME 
) 
INSERT INTO Test VALUES 
('20150311'), ('20150312'), ('20150313'), ('20150316'); 

DECLARE @startDate DATE = '20150311' 
DECLARE @endDate DATE = '20150317' 

;WITH Cte AS(
    SELECT 
     *, 
     RN = DATEADD(DD, - (ROW_NUMBER() OVER(ORDER BY tDATE) - 1), tDate) 
    FROM Test 
    WHERE 
     tDate >= @startDate 
     AND tDate < DATEADD(DAY, 1, @endDate) 
) 
SELECT CAST(tDate AS DATE) 
FROM CTE 
WHERE RN = @startDate 

RISULTATO

|------------| 
| 2015-03-11 | 
| 2015-03-12 | 
| 2015-03-13 | 

Ecco la versione 2005 di SQL Server:

SQL Fiddle

DECLARE @startDate DATETIME 
DECLARE @endDate DATETIME 

SET @startDate = '20150311' 
SET @endDate = '20150317' 

;WITH Cte AS(
    SELECT 
     *, 
     RN = DATEADD(DD, -(ROW_NUMBER() OVER(ORDER BY tDATE)-1), tDate) 
    FROM Test 
    WHERE 
     tDate >= @startDate 
     AND tDate < DATEADD(DAY, 1, @endDate) 
) 
SELECT CONVERT(VARCHAR(10), tDate, 121) 
FROM CTE 
WHERE RN = @startDate 
+0

Nel tuo codice tutto funziona bene. ma per la data di fine sembra avere qualche problema. come se la data di inizio fosse '20150311' e la data di fine fosse '20150312' quindi mostrasse i risultati 2015-03-11 2015-03-12 2015-03-13. Ma dovrebbe essere 2015-03-11 2015-03-12 –

+0

Oh, mi dispiace. Dovrebbe essere 'tdate

+0

grazie al suo funzionamento @wewesthemenace –

-2

Usa BETWEEN

La query andrà in questo modo:

SELECT * 
FROM your_table_name 
WHERE your_date_column_name BETWEEN '2015-3-11' AND '2015-3-13' 
-2

(dt between x and y) o semplicemente (dt >= x and dt <= y).

1

non è necessario dichiarare qualsiasi data di inizio o di fine, come altre risposte dice, è necessario un row_num con datediff funzione:

create table DateFragTest (cDate date); 
insert into DateFragTest 
     values ('2015-3-11'), 
       ('2015-3-12'), 
       ('2015-3-13'), 
       ('2015-3-16') 

    with cte as 
     (select 
     cDate, 
     row_number() over (order by cDate) as rn 
     from 
     DateFragTest) 
    select cDate 
    from cte t1 
    where datediff(day, 
        (select cDate from cte t2 where t2.rn=t1.rn+1), 
        t1.cDate)<>1 

uscita:

cDate 
2015-03-11 
2015-03-12 
2015-03-13 

SQLFIDDLE DEMO

2

per MSSQL 2012.Ciò restituirà MAX gruppi continue:

DECLARE @t TABLE(d DATE) 

INSERT INTO @t VALUES 
('20150311'), 
('20150312'), 
('20150313'), 
('20150316') 


;WITH 
c1 AS(SELECT d, IIF(DATEDIFF(dd,LAG(d, 1, DATEADD(dd, -1, d)) OVER(ORDER BY d), d) = 1, 0, 1) AS n FROM @t), 
c2 AS(SELECT d, SUM(n) OVER(ORDER BY d) AS n FROM c1) 

SELECT TOP 1 WITH TIES MIN(d) AS StartDate, MAX(d) AS EndDate, COUNT(*) AS DayCount 
FROM c2 
GROUP BY n 
ORDER BY DayCount desc 

uscita:

StartDate EndDate  DayCount 
2015-03-11 2015-03-13 3 

Per

('20150311'), 
('20150312'), 
('20150313'), 
('20150316'), 
('20150317'), 
('20150318'), 
('20150319'), 
('20150320') 

uscita:

StartDate EndDate  DayCount 
2015-03-16 2015-03-20 5 

applicare il filtro in c1 CTE:

c1 AS(SELECT d, IIF(DATEDIFF(dd,LAG(d, 1, DATEADD(dd, -1, d)) OVER(ORDER BY d), d) = 1, 0, 1) AS n FROM @t WHERE d BETWEEN '20150311' AND '20150320'), 

Per MSSQL 2008:

;WITH 
c1 AS(SELECT d, (SELECT MAX(d) FROM @t it WHERE it.d < ot.d) AS pd FROM @t ot), 
c2 AS(SELECT d, CASE WHEN DATEDIFF(dd,ISNULL(pd, DATEADD(dd, -1, d)), d) = 1 THEN 0 ELSE 1 END AS n FROM c1), 
c3 AS(SELECT d, (SELECT SUM(n) FROM c2 ci WHERE ci.d <= co.d) AS n FROM c2 co) 

SELECT TOP 1 WITH TIES MIN(d) AS StartDate, MAX(d) AS EndDate, COUNT(*) AS DayCount 
FROM c3 
GROUP BY n 
ORDER BY DayCount desc 
1

Per sql server 2012 -

WITH cte 
AS 
(
    SELECT [datex] 
    ,  lead([datex]) OVER (ORDER BY [datex]) lead_datex 
    ,  datediff(dd,[datex],lead([datex]) OVER (ORDER BY [datex])) AS diff 
    FROM [dbo].[datex] 
) 
SELECT c.[datex] 
FROM [cte] AS c 
WHERE diff >=1 

enter image description here

Problemi correlati