[英]SQL query sum by month and put years as columns
I have the following query 我有以下查询
SELECT
MONTH(PaymentDate) AS [month],
YEAR(PaymentDate) AS [year],
SUM(OutstandingPayment) AS totalCollected
FROM
Payments
WHERE
PaymentDate BETWEEN '01/01/2016' AND '12/31/2017'
GROUP BY
YEAR(PaymentDate), MONTH(PaymentDate)
ORDER BY
YEAR(PaymentDate), MONTH(PaymentDate)
The output is below 输出如下
month year totalCollected
----------------------------------
1 2016 10000
2 2016 11000
3 2016 12000
4 2016 13000
5 2016 14000
6 2016 15000
7 2016 16000
8 2016 17000
9 2016 18000
10 2016 19000
11 2016 20000
12 2016 21000
1 2017 11000
2 2017 12000
3 2017 13000
4 2017 14000
5 2017 15000
6 2017 16000
7 2017 17000
8 2017 18000
9 2017 19000
10 2017 20000
11 2017 21000
12 2017 22000
I would like the output to be 我希望输出是
Month 2016 2017 $Change %Change
----------------------------------------
1 10000 11000 1000 10.00%
2 11000 12000 1000 9.09%
3 12000 13000 1000 8.33%
4 13000 14000 1000 7.69%
5 14000 15000 1000 7.14%
6 15000 16000 1000 6.67%
7 16000 17000 1000 6.25%
8 17000 18000 1000 5.88%
9 18000 19000 1000 5.56%
10 19000 20000 1000 5.26%
11 20000 21000 1000 5.00%
12 21000 22000 1000 4.76%
The $change
is 2017 data - 2016 data. $change
是2017数据-2016数据。 The percent change is ((2016 Data - 2017 Data)/2017 Data). 百分比变化为((2016年数据-2017年数据)/ 2017年数据)。
How do I pivot the data and add the calculated columns? 如何旋转数据并添加计算出的列?
Thanks in advance. 提前致谢。
Use conditional aggregation: 使用条件聚合:
select month(PaymentDate) as [month],
sum(case when year(PaymentDate) = 2016 then OutstandingPayment end) as totalCollected_2016,
sum(case when year(PaymentDate) = 2017 then OutstandingPayment end) as totalCollected_2017,
sum(case when year(PaymentDate) = 2017 then OutstandingPayment
when year(PaymentDate) = 2016 then -OutstandingPayment
end) as diff,
( (sum(case when year(PaymentDate) = 2017 then OutstandingPayment end) /
sum(case when year(PaymentDate) = 2016 then OutstandingPayment end)
) - 1
) as increase
from Payments p
where PaymentDate BETWEEN '2016-01-01' AND '2017-12-31'
group by month(PaymentDate)
order BY month(PaymentDate);
Another option is with a PIVOT in concert with a CTE 另一个选择是与CTE一起使用PIVOT
Example 例
;with cte as (
Select *
From (
select month(PaymentDate) as [month], year(PaymentDate) as [year], sum(OutstandingPayment) as totalCollected
FROM Payments
WHERE PaymentDate BETWEEN '01/01/2016' AND '12/31/2017'
group by year(PaymentDate), month(PaymentDate)
) A
Pivot (sum(totalCollected) for year in ([2016],[2017]) ) pvt
)
Select *
,[$Change] = [2017]-[2016]
,[%Change] = (([2017]-[2016])*100) / NullIf([2016],0)
From cte
Order By [month]
Returns 返回
You could use a join 您可以使用联接
select a. month
, a.totalCollected
, b.totalCollected - a.totalCollected as ` $Change`
, ( b.totalCollected - a.totalCollected) / a.totalCollected ` %Change`
from my_table ainner join my_table b on a.month = b.month and a.year = '2016' and b.year = '2017'
select a. month
, a.totalCollected
, b.totalCollected - a.totalCollected as ` $Change`
, ( b.totalCollected - a.totalCollected) / a.totalCollected ` %Change`
from (
select month(PaymentDate) as [month], year(PaymentDate) as [year], sum(OutstandingPayment) as totalCollected
FROM Payments
WHERE PaymentDate BETWEEN '01/01/2016' AND '12/31/2017'
group by year(PaymentDate), month(PaymentDate)
ORDER BY year(PaymentDate), month(PaymentDate)
) a
inner join (
select a. month
, a.totalCollected
, b.totalCollected - a.totalCollected as ` $Change`
, ( b.totalCollected - a.totalCollected) / a.totalCollected ` %Change`
from my_table ainner join my_table b on a.month = b.month and a.year = '2016' and b.year = '2017'
) b on a.month = b.month and a.year = '2016' and b.year = '2017'
and you could use a view for avoid code duplication 您可以使用视图来避免代码重复
create view my_view as
select month(PaymentDate) as [month], year(PaymentDate) as [year], sum(OutstandingPayment) as totalCollected
FROM Payments
WHERE PaymentDate BETWEEN '01/01/2016' AND '12/31/2017'
group by year(PaymentDate), month(PaymentDate)
ORDER BY year(PaymentDate), month(PaymentDate)
select a. month
, a.totalCollected
, b.totalCollected - a.totalCollected as ` $Change`
, ( b.totalCollected - a.totalCollected) / a.totalCollected ` %Change`
from (
my_view
) a
inner join (
my_view
) b on a.month = b.month and a.year = '2016' and b.year = '2017'
By having a subquery that is grouped by month and have payments separated by year using a case statement: 通过使用case语句使子查询按月分组并按年分隔付款:
SELECT [month],
[2016_TOTAL] as [2016],
[2017_TOTAL] as [2017],
([2017_TOTAL] - [2016_TOTAL]) as [$Change]
(([2016_TOTAL] - [2017_TOTAL])/[2017_TOTAL]) as [%Change]
FROM
(
SELECT
MONTH(PaymentDate) AS [month],
SUM(CASE WHEN YEAR(PaymentDate)='2016' then OutstandingPayment) AS [2016_TOTAL],
SUM(CASE WHEN YEAR(PaymentDate)='2017' then OutstandingPayment) AS [2017_TOTAL]
FROM
Payments
WHERE
PaymentDate BETWEEN '01/01/2016' AND '12/31/2017'
GROUP BY
MONTH(PaymentDate)
) temp
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.