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

Die obige Abfrage mir das Ergebnis für den Campaign_id ‚s gibt, die auf jedes Datum zwischen 2015.03.01 und 2015.03.31 aktiv waren.SQL: Where-Klausel

Ich möchte das Ergebnis enthalten die campaign_id 's, wenn die auf allen die Daten zwischen 2015-03-01 und 2015-03-31 aktiv waren.

Wie würde ich darüber gehen?

Antwort

6

Angenommen DATE ist ein DATE Datentyp und hat keine Zeitkomponente.

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); 

oder eine Version ohne die Variablen

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

Funktioniert gut, gibt mir das Ergebnis, das ich will. Wäre toll, wenn du mir erzählen könntest, wie die letzte Zeile funktioniert, habe ich das nicht verstanden. –

+2

@TauseefHussain - Wenn sie an jedem Datum im März aktiv waren, was bedeuten würde, dass sie an 31 verschiedenen Tagen in diesem Monat aktiv waren, vermeidet das 'DATEDIFF' nur das Festschreiben dieser Nummer. –

+0

Klar jetzt, vielen Dank. –

4

Mit HAVING Klausel mit 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; 

Sie sollten auch diese blog post von Aaron Betrand überprüfen zu verstehen, warum BETWEEN mit für Termine ist eine schlechte Idee.

Sie können die Abfrage machen organisieren nur die Daten einmal erwähnen, indem Sie so etwas wie:

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); 

Hinweis: Einige würden es vorziehen, eine JOIN einen CROSS JOIN in diesem Fall. Aus Gewohnheit habe ich immer eine Parameter CTE in eine Abfrage mit CROSS JOIN.

+2

es ist nichts falsch mit der Verwendung zwischen für Termine, das Problem besteht nur bei der Verwendung von Datumsangaben –

+0

Works perfekt, danke. –