SQL:Where子句

时间:2015-06-21 15:04:42

标签: sql sql-server

SELECT DISTINCT Campaign_id 
FROM Impressions 
WHERE Date BETWEEN '2015-03-01' AND '2015-03-31' ;

以上查询为我提供了2015-03-01和2015-03-31之间任何日期活跃的Campaign_id的结果。

如果所有在2015-03-01和2015-03-31之间的日期一直有效,我希望结果集包含campaign_id

我该怎么做?

2 个答案:

答案 0 :(得分:6)

假设DATEDATE数据类型并且没有时间组件。

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

或没有变量的版本

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

答案 1 :(得分:4)

HAVING子句与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;

您还应该查看Aaron Betrand的blog post,了解为什么在日期中使用BETWEEN是一个坏主意。

您可以通过执行以下操作来安排查询,只提及日期:

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

注意:在这种情况下,有些人更喜欢JOINCROSS JOIN。根据习惯,我总是使用CROSS JOIN在查询中放置参数CTE。