I'm writing a little query that builds a count of rows per month&year, to mimic the behavior you'd see in google analytics.
this is my query:
USE MyDatabase;
SELECT
COUNT(*) AS Rows,
DATENAME(mm, OpenDate) AS Month,
DATENAME(yyyy, OpenDate) AS Year
FROM MyTable
WHERE Priority = 1
GROUP BY DATENAME(mm, OpenDate), DATENAME(yyyy, OpenDate)
ORDER BY Year, Month DESC;
I'm unclear as to how I'd apply a date range filter in this query.
HAVING
or WHERE
?答案 0 :(得分:3)
或者,您也可以将日期时间字段(OpenDate)转换为日期,并执行以下操作:
USE MyDatabase;
DECLARE @StartDate DATE
,@EndDate DATE
SET @StartDate = '2015-05-01'
SET @EndDate = '2015-05-30'
BEGIN
SELECT COUNT(*) AS Rows
,DATENAME(mm, OpenDate) AS Month
,DATENAME(yyyy, OpenDate) AS Year
FROM MyTable
WHERE Priority = 1
AND CAST(OpenDate AS DATE) BETWEEN @StartDate
AND @EndDate
GROUP BY DATENAME(mm, OpenDate)
,DATENAME(yyyy, OpenDate)
ORDER BY Year,Month DESC;
END
VS HAVING?
WHERE
子句在执行聚合之前限制数据,而HAVING
子句在执行聚合之后限制数据。
使用WHERE
子句总是更好,因为不需要让计算机计算聚合然后将其过滤掉。
答案 1 :(得分:2)
正如@bluefeet所说,这通常应该起作用:
WHERE OpenDate >= @Date1 and OpenDate <= @Date2
我应该使用HAVING还是WHERE?
WHERE。
HAVING用于在分组和聚合后过滤,所以一个好的经验法则是你只需要在需要引用像HAVING COUNT(*) > 10
这样的聚合函数时使用它。另外,请记住HAVING子句中的每个字段也必须位于GROUP BY或聚合中。它可以在这里工作,但除非你知道你需要它,否则避免HAVING是更好的逻辑。通常,您可以越早过滤数据集中的内容,处理的速度越快,GROUP BY之前的WHERE进程。
我是否需要为我的vars使用完全形成的日期时间字符串?或者我分开过滤年份和月份,因为我有这些列?
制作完整日期或日期时间通常最简单。你将在某个时刻跨越年界,如果你不这样做,那将是一个巨大的痛苦。如果你想要2014年11月到2015年1月怎么办?或2013年5月至2015年5月?
您唯一需要决定的是,您是否或如何汇总分数月份。那么,该应用程序是否允许用户说他们想要2014年6月23日到2014年7月13日?
如果他们这样做了,你会退回吗,或者你是否在6月和7月归还了所有内容而忽略了他们选择了特定日期的事实?
如果是前者,那么@ bluefeet的回答很好:
WHERE OpenDate >= @Date1 and OpenDate <= @Date2
如果没有,那么您可能需要修改日期标准。通常,你会想说:
WHERE OpenDate >= {First Date Of Date1's Month}
AND OpenDate < {First Date of Month After Date2 Month}
因此,如果您想从2014年6月23日到2015年1月13日,那么看起来像是:
WHERE OpenDate >= '2014-06-01'
AND OpenDate < '2015-01-01'
这样做意味着您不必担心一个月内有多少天。在将应用程序提交到查询引擎之前,通常可以在应用程序中处理日期数学,但可以使用CAST(),YEAR(),MONTH()和DATEADD()在SQL中完成。