我正在使用SQL Server 2008 R2。我正在尝试创建一个按3M,6M,9M,12M总计汇总总计的查询。以下是一些示例数据:
create table invoice (store int, invoice_date datetime, customer int, is_repeat varchar(1));
insert into invoice (store, invoice_date, customer, is_repeat)
values (1, '2015-10-05', 1, 'N'),
(1, '2016-03-04', 1, 'Y'),
(1, '2016-02-07', 1, 'Y'),
(1, '2015-08-03', 2, 'Y'),
(2, '2015-12-01', 3, 'Y'),
(2, '2016-02-16', 4, 'Y'),
(2, '2015-06-11', 3, 'Y'),
(2, '2015-09-18', 4, 'Y');
查询需要提供3M,6M等数量的' Y'值,按商店,月份和年份汇总。例如,2016年3月的商店1应该有一个记录,总数为' Y'在2015年12月1日和2016年2月29日之间的值,并将该值放在3M列中。然后将9/1/2015和02/29/2016之间的值相加,并将这些值放在6M列中。
以下是上述数据的查询结果示例:
STORE MONTH YEAR 3M_REPEATS 6M_REPEATS
----- ----- ---- ---------- ----------
1 2 2016 0 2
1 3 2016 1 2
2 2 2016 1 3
2 3 2016 2 3
我试图找到一个优雅的解决方案,但我不确定我是应该使用CTE,PIVOT还是OVER(PARTITION BY),还是仅使用标准的GROUP BY子句。
编辑添加:我最终只需要这个表中的最后12个月,因此此表中只有12条记录。例如,如果当前月/年为2016年3月,它将具有2/2015 - 3/2016以及每月的总计。
答案 0 :(得分:1)
通过使用案例陈述来获取每个季度的记录,然后使用分组
select
store,
datepart(m, invoice_date) as mth,
datepart(yyyy, invoice_date) as yr,
Sum(case when datename(qq,invoice_date)=1 then 1 else 0 end) as QTR1,
Sum(case when datename(qq,invoice_date)=2 6 then 1 else 0 end) as QTR2
FROM test
WHERE is_repeat='Y'
GROUP BY store, datepart(m, t.invoice_date), datepart(yyyy, t.invoice_date)
ORDER BY store, mth, yr
答案 1 :(得分:0)
我会为聚合和GROUP BY Store,Month,Year提供SUM CASE表达式。
答案 2 :(得分:0)
这是一个使用分析函数的版本:
with agg as (
select
store,
min(invoice_date) as invoice_month,
count(case when is_repeat = 'Y' then 1 end) as y_count
from invoice
where
invoice_date >= dateadd(month, -14, current_timestamp)
and datediff(month, invoice_date, current_timestamp) between 1 and 12
group by
store,
datediff(month, invoice_date, current_timestamp)
)
select
store,
datepart(month, a1.invoice_month) as "month",
datepart(year, a1.invoice_month) as "year",
sum(y_count) over (
partition by store
order by invoice_month
rows between 2 preceding and current row
) as 3m_repeats,
sum(y_count) over (
partition by store
order by invoice_month
rows between 5 preceding and current row
) as 6m_repeats
from agg
但是,由于你不能在2008年使用rows between
,我认为这可以替代:
with agg as (
select
store,
min(invoice_date) as invoice_month,
count(case when is_repeat = 'Y' then 1 end) as y_count
from invoice
where
invoice_date >= dateadd(month, -14, current_timestamp)
and datediff(month, invoice_date, current_timestamp) between 1 and 12
group by
store,
datediff(month, invoice_date, current_timestamp)
)
select
store,
datepart(month, a1.invoice_month) as "month",
datepart(year, a1.invoice_month) as "year",
sum(case
when datediff(month, a1.invoice_date, a2.invoice_date)
between -2 and 0
then y_count end
) as 3m_repeats,
sum(case
when datediff(month, a1.invoice_date, a2.invoice_date)
between -5 and 0 then y_count end
) as 6m_repeats,
from agg a1 inner join agg a2
on a2.store = a1.store
and datediff(month, a1.invoice_date, a2.invoice_date) between -5 and 0
group by a1.store, a1.invoice_month
我假设你有所有月份的数据,所以我没有打扰这个并发症。