Sql server SQL:生成过去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 -----+-------+-----------+-----------

使用SQLServer2008R2,我编写了一些代码来生成一个聚合结果表,该表计算当月所有约会的平均等待时间(从转诊到约会日期)

无论查询运行在哪一天,我都希望它为我生成一个前12个完整月份的结果表,不包括当前月份。例如,如果我今天(2017年9月6日)运行查询,我希望结果表在2017年8月至2016年9月的12个月内给出12行,如下所示:

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个月前的第一天。检查下面我的答案