Sql server SQL:生成过去12个月(不包括本月)的聚合结果表
使用SQLServer2008R2,我编写了一些代码来生成一个聚合结果表,该表计算当月所有约会的平均等待时间(从转诊到约会日期) 无论查询运行在哪一天,我都希望它为我生成一个前12个完整月份的结果表,不包括当前月份。例如,如果我今天(2017年9月6日)运行查询,我希望结果表在2017年8月至2016年9月的12个月内给出12行,如下所示:Sql server SQL:生成过去12个月(不包括本月)的聚合结果表,sql-server,sql-server-2008,tsql,Sql Server,Sql Server 2008,Tsql,使用SQLServer2008R2,我编写了一些代码来生成一个聚合结果表,该表计算当月所有约会的平均等待时间(从转诊到约会日期) 无论查询运行在哪一天,我都希望它为我生成一个前12个完整月份的结果表,不包括当前月份。例如,如果我今天(2017年9月6日)运行查询,我希望结果表在2017年8月至2016年9月的12个月内给出12行,如下所示: YEAR | MONTH | MONTHNAME | AVG DAYS WAIT -----+-------+-----------+-----------
YEAR | MONTH | MONTHNAME | AVG DAYS WAIT
-----+-------+-----------+---------------
2017 | 8 | August | 42
2017 | 7 | July | 43
2017 | 6 | June | 47
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2016 | 9 | September | 42
我使用的代码确实返回了一个12个月的列表,不包括当前月份:
SELECT
year (OP.Appointment_Date) [Year]
,month (OP.Appointment_Date) [Month]
,DATENAME (month,OP.Appointment_Date) [MonthName]
,AVG(DATEDIFF (dd,OP.Received_Date,Appointment_Date)) [Avg Days Wait]
FROM
[HDM_Local].[Outpatients].[vw_OP_Appointments] OP WITH (NOLOCK)
WHERE
OP.Appointment_Date >= DATEADD(month, -12, GETDATE())
AND OP.Appointment_Date < DATEADD(month, -1, GETDATE())
GROUP BY
year(OP.Appointment_Date)
,month(OP.Appointment_Date)
,DATENAME(month,OP.Appointment_Date)
ORDER BY
year(OP.Appointment_Date)desc
,month(OP.Appointment_Date)desc
选择
年份(OP.任命日期)[年份]
,月(OP.Appointment_Date)[月]
,日期名称(月,OP.Appointment_日期)[MonthName]
,平均(DATEDIFF(dd,OP.Received_Date,Appointment_Date))[平均等待天数]
从…起
[HDM_本地].[门诊].[vw_门诊预约]门诊(诺洛克)
哪里
OP.Appointment\u Date>=DATEADD(月-12,GETDATE())
和OP.Appointment_Date
然而,我发现的问题是最近一个月(8月)的结果不正确
通过验证我的数据,我知道8月份的平均等待时间为42天。上面的查询实际上给了我一个50的数字
我假设现在发生的是和OP.Appointment\u Date
语句取今天的日期,从中减去整整一个月的天数,然后仅根据8月1日至6日之间的约会计算8月份约会的平均等待时间(或者类似的东西)
同样的问题似乎也影响了列表中最老月份的结果,我再次假设,因为在执行计算时,它忽略了2016年9月的前5/6天
请任何人解释一下,如何对语句进行编码,使其有效地“忽略当前月份并根据每个月内的全部日期返回前12个月”您的
中的子句是减去月份,但不是截断到每个月的开始
这将为您提供从12个月前一个月的第一天到上个月底的范围:
where op.Appointment_Date >= dateadd(month, datediff(month, 0, getdate() )-12, 0)
and op.Appointment_Date < dateadd(month, datediff(month, 0, getdate() ), 0)
rextester演示:
返回:
+------------------+---------------------+---------------------+
| TruncatedToMonth | fromdate | thrudate |
+------------------+---------------------+---------------------+
| N | 2016-09-06 14:38:07 | 2017-08-06 14:38:07 |
| Y | 2016-09-01 00:00:00 | 2017-09-01 00:00:00 |
+------------------+---------------------+---------------------+
您的where
子句是减去月份,但不是截断到每个月的开始
这将为您提供从12个月前一个月的第一天到上个月底的范围:
where op.Appointment_Date >= dateadd(month, datediff(month, 0, getdate() )-12, 0)
and op.Appointment_Date < dateadd(month, datediff(month, 0, getdate() ), 0)
rextester演示:
返回:
+------------------+---------------------+---------------------+
| TruncatedToMonth | fromdate | thrudate |
+------------------+---------------------+---------------------+
| N | 2016-09-06 14:38:07 | 2017-08-06 14:38:07 |
| Y | 2016-09-01 00:00:00 | 2017-09-01 00:00:00 |
+------------------+---------------------+---------------------+
在哪里
OP.Appointment_Date>=DATEADD(月,DATEDIFF(月,0,GETDATE())-12,0)
和OP.Appointment_Date
--或--
在哪里
OP.Appointment\u日期添加(月,日期差异(月,0,GETDATE())-12,0)之间的日期
和DATEADD(MONTH,DATEDIFF(MONTH,-1,GETDATE())-1,-1)
基本上:
选择DATEADD(MONTH,DATEDIFF(MONTH,0,GETDATE())-1,0--上个月的第一天
选择DATEADD(MONTH,DATEDIFF(MONTH,-1,GETDATE())-1,-1--上个月的最后一天
OP.Appointment_Date>=DATEADD(月,DATEDIFF(月,0,GETDATE())-12,0)
和OP.Appointment_Date
--或--
在哪里
OP.Appointment\u日期添加(月,日期差异(月,0,GETDATE())-12,0)之间的日期
和DATEADD(MONTH,DATEDIFF(MONTH,-1,GETDATE())-1,-1)
基本上:
选择DATEADD(MONTH,DATEDIFF(MONTH,0,GETDATE())-1,0--上个月的第一天
选择DATEADD(MONTH,DATEDIFF(MONTH,-1,GETDATE())-1,-1)--上个月的最后一天我个人会从where子句中删除您的逻辑,并将它们放入变量中,因为它们不依赖于列(这将减少您的开销,根据您的数据库而定,这可以忽略不计,也可以减少大量开销)
在where子句中尝试这些变量,应返回2016年9月初至2017年8月底
DECLARE @MinDate DATE = DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE())-12, 0) -- Get start of month 13 months before current
DECLARE @MaxDate DATE = DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), -1) -- Get end of latest month before current
SELECT @MinDate, @MaxDate
编辑:只需重新阅读您的帖子。DATEADD MONTH
的工作方式是,从日期开始增加或减少月份数,即如果是2017年9月6日,则从返回2016年9月6日的日期开始计算12个月。您始终可以从WHERE子句中提取类似的子句,并将其放入选择到中查看它们所产生的效果,即:
SELECT DATEADD(month, -12, GETDATE()), DATEADD(month, -1, GETDATE())
返回
(No column name) (No column name)
2016-09-06 18:45:07.857 2017-08-06 18:45:07.857
我个人会从where子句中删除您的逻辑,并将它们放入一个变量中,因为它们不依赖于列(这将减少您的开销,这取决于您的数据库)
在where子句中尝试这些变量,应返回2016年9月初至2017年8月底
DECLARE @MinDate DATE = DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE())-12, 0) -- Get start of month 13 months before current
DECLARE @MaxDate DATE = DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), -1) -- Get end of latest month before current
SELECT @MinDate, @MaxDate
编辑:只需重新阅读您的帖子。DATEADD MONTH
的工作方式是,从日期开始增加或减少月份数,即如果是2017年9月6日,则从返回2016年9月6日的日期开始计算12个月。您始终可以从WHERE子句中提取类似的子句,并将其放入选择到中查看它们所产生的效果,即:
SELECT DATEADD(month, -12, GETDATE()), DATEADD(month, -1, GETDATE())
返回
(No column name) (No column name)
2016-09-06 18:45:07.857 2017-08-06 18:45:07.857
你应该检查上个月的最后一个日期和12个月前的第一个日期。检查下面我的答案。@Ravi,谢谢你的帮助。类似于我之前对SqlZim的回复,我正在尝试运行这个,但在30分钟以上仍在运行后终止它。当我得到结果时,我会给出反馈。首先尝试使用较少的数据,然后我们尝试优化你应该检查上个月的最后一天和12个月前的第一天。检查下面我的答案