我在两个表中有数据ORDERS
和training
。为各种客户提供不同类型的培训。我想看看这些培训对相关客户的收入有什么影响。为了实现这一目标,我想查看每个客户从接受培训之日起过去 90 天和未来 90 天的收入。换句话说,如果客户在 2014 年 3 月 30 日接受了培训,我想查看从 2014 年 1 月 1 日到 2014 年 6 月 30 日的收入。我想出了以下查询,它几乎可以完成这项工作:
select
o.custno,
sum(ISNULL(a.revenue,0)) as Revenue,
o.Date as TrainingDate,
DATEADD(mm, DATEDIFF(mm, 0, a.created), 0) as RevenueMonth
from ORDERS a,
(select distinct custno, max(Date) as Date from Training group by custno) o
where a.custnum = o.custno
and a.created between DATEADD(day, -90, o.Date) and DATEADD(day, 90, o.Date)
group by o.custno, o.Date, DATEADD(mm, DATEDIFF(mm, 0, a.created), 0)
order by o.custno
此查询的示例输出如下所示:
custno Revenue TrainingDate RevenueMonth
0000100 159.20 2014-06-02 00:00:00.000 2014-03-01 00:00:00.000
0000100 199.00 2014-06-02 00:00:00.000 2014-04-01 00:00:00.000
0000100 79.60 2014-06-02 00:00:00.000 2014-05-01 00:00:00.000
0000100 29.85 2014-06-02 00:00:00.000 2014-06-01 00:00:00.000
0000100 79.60 2014-06-02 00:00:00.000 2014-07-01 00:00:00.000
0000100 99.50 2014-06-02 00:00:00.000 2014-08-01 00:00:00.000
0000250 437.65 2013-02-26 00:00:00.000 2012-11-01 00:00:00.000
0000250 4181.65 2013-02-26 00:00:00.000 2012-12-01 00:00:00.000
0000250 4146.80 2013-02-26 00:00:00.000 2013-01-01 00:00:00.000
0000250 6211.93 2013-02-26 00:00:00.000 2013-02-01 00:00:00.000
0000250 2199.72 2013-02-26 00:00:00.000 2013-03-01 00:00:00.000
0000250 4452.65 2013-02-26 00:00:00.000 2013-04-01 00:00:00.000
所需的输出示例:
如果培训是在 2014 年 3 月 15 日提供的,对于客户编号 100,我需要以下格式的收入数据:
CustNo Revenue TrainingDate RevenueMonth
100 <Some revenue figure> March 15 2014 Dec 15 2013 – Jan 14 2014 (Past month 1)
100 <Some revenue figure> March 15 2014 Jan 15 2014 – Feb 14 2014 (Past month 2)
100 <Some revenue figure> March 15 2014 Feb 15 2014 – Mar 14 2014 (Past month 3)
100 <Some revenue figure> March 15 2014 Mar 15 2014 – Apr 14 2014 (Future month 1)
100 <Some revenue figure> March 15 2014 Apr 15 2014 – May 14 2014 (Future month 2)
100 <Some revenue figure> March 15 2014 May 15 2014 – Jun 14 2014 (Future month 3)
在这里,只要RevenueMonth
列具有与训练日期相关的数据,就不需要采用这种格式。大括号中的"过去"和"未来"月份引用仅用于解释输出,它们不必出现在输出中。
我的查询获取数据并按月对数据进行分组。我希望相对于培训日期对月份进行分组。例如 - 如果培训是在 3 月 15 日进行的,我希望过去一个月是从 2 月 15 日到 3 月 14 日,我的查询不会这样做。我相信在这个查询中进行一些调整可能会达到我所追求的。
任何有关查询的帮助将不胜感激。
类似这些行的内容可能会做你想要的:
select
t.custno,
sum(ISNULL(o.revenue,0)) as Revenue,
t.maxDate as TrainingDate,
((DATEDIFF(day, TrainingDate, o.created) + 89) / 30) - 3 as DeltaMonth
from ORDERS o
join (select custno, max([Date]) as maxDate from Training group by custno) t
on o.custnum = t.custno
where o.created
between DATEADD(day, -89, t.maxDate) and DATEADD(day, 90, t.maxDate)
group by t.custno, t.maxDate, DeltaMonth
order by t.custno
一般策略是计算与训练日期相比的月差(实际上是 30 天(,并按此分组。 此版本使用从训练前 89 天到训练后 90 天,因为如果您从 -90 运行到 +90,那么您将多一天(训练日本身(而不是平均分为 30 天。
查询遵循原始查询的一般结构,但有几项更改:
- 它将
DeltaMonth
(从 -3 到 2(计算为相对于训练日期的 30 天周期的索引,训练日期是数字 -1DeltaMonth
的最后一天。 - 它在
GROUP BY
子句中使用DeltaMonth
别名,而不是重复其公式。 这提供了更好的清晰度、简单性和可维护性。 - 我更改了表别名。 我根本无法处理一个名为"ORDERS"的表和别名"o",后者与前者无关。
- 该查询使用新式联接语法,以便更清晰
- 适当更新
GROUP BY
条款