2015-06-21 11 views
5
SELECT DISTINCT Campaign_id 
FROM Impressions 
WHERE Date BETWEEN '2015-03-01' AND '2015-03-31' ; 

La query sopra mi dà il risultato per la 's Campaign_id che sono stati attivi su qualsiasi data compresa tra 2015/03/01 e 2015/03/31.SQL: Dove clausola

Voglio che il set di risultati contenga gli campaign_id se sono stati attivi su tutte le le date tra 2015-03-01 e 2015-03-31.

Come dovrei fare questo?

risposta

6

Supponendo che DATE sia un tipo di dati DATE e non abbia componente orario.

DECLARE @Start DATE = '2015-03-01', 
     @End DATE = '2015-03-31' 

SELECT Campaign_id 
FROM Impressions 
WHERE Date BETWEEN @Start AND @End 
GROUP BY Campaign_id 
HAVING COUNT(DISTINCT Date) = 1 + DATEDIFF(DAY, @Start, @End); 

O una versione senza le variabili

SELECT Campaign_id 
FROM Impressions 
     CROSS APPLY (VALUES ({ d '2015-03-01' }, 
          { d '2015-03-31' })) V([Start], [End]) 
WHERE [Date] BETWEEN [Start] AND [End] 
GROUP BY Campaign_id, [Start], [End] 
HAVING COUNT(DISTINCT Date) = 1 + DATEDIFF(DAY, [Start], [End]); 
+0

Funziona alla grande, mi dà il risultato che voglio. Sarebbe bello se tu potessi dirmi come funziona l'ultima linea, non l'ho capito. –

+2

@TauseefHussain - Se fossero attive tutte le date di marzo che significherebbero essere attive per 31 giorni distinti in quel mese, il 'DATEDIFF' evita solo di codificare questo numero. –

+0

Cancella ora, grazie mille. –

4

Uso HAVING clausola con COUNT(DISTINCT):

SELECT Campaign_id 
FROM Impressions 
WHERE Date between '2015-03-01' and '2015-03-31' 
GROUP BY Campaign_id 
HAVING COUNT(DISTINCT Date) = 31; 

Si dovrebbe anche su questo blog post da Aaron Betrand per capire il motivo per cui utilizzando BETWEEN per le date è una cattiva idea.

È possibile rendere organizzare la query per citare solo le date, una volta facendo qualcosa di simile:

WITH params as (
     SELECT CAST('2015-03-01' as DATE) as date1, CAST('2015-03-31' as DATE) date2 
    ) 
SELECT i.Campaign_id 
FROM params CROSS JOIN 
    Impressions i 
WHERE i.Date >= params.Date1 and i.Date < DATEADD(day, 1, params.Date2) 
GROUP BY i.Campaign_id, params.date1, params.date2 
HAVING COUNT(DISTINCT i.Date) = 1 + DATEDIFF(day, params.date1, params.date2); 

Nota: alcuni preferirebbero un JOIN ad un CROSS JOIN in questo caso. Per abitudine, inserisco sempre un parametro CTE in una query usando CROSS JOIN.

+2

non c'è niente di sbagliato nell'usare tra le date, il problema esiste solo quando si utilizza il datario –

+0

Funziona perfettamente, grazie. –