按月查询SQL查询并将年份作为列

时间:2018-02-09 17:14:28

标签: sql sql-server-2008

我有以下查询

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)

输出低于

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

我希望输出为

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%

$change是2017年数据 - 2016年数据。变化百分比为((2016年数据 - 2017年数据)/ 2017年数据)。

如何透视数据并添加计算列?

提前致谢。

4 个答案:

答案 0 :(得分:1)

使用条件聚合:

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);

答案 1 :(得分:1)

另一种选择是将PIVOT与CTE协调一致

示例

;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]

<强>返回

enter image description here

答案 2 :(得分:0)

您可以使用联接

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'

您可以使用视图来避免代码重复

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'

答案 3 :(得分:0)

通过使用按月分组的子查询,并使用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