使用数据透视时按问题排序

时间:2018-01-04 07:18:16

标签: sql sql-server tsql pivot

我有查询的源表

SELECT 
    DATENAME(MONTH, sales_timestamp) as Month_Name, COUNT(nc_deposit) as piece, 
    ISNULL(sum(nc_deposit),0) as amount,terminal_name
FROM dbfastshosted.dbo.fh_mf_new_card_logs cl
INNER JOIN dbfastshosted.dbo.fh_sales_map m 
    on cl.nc_log_id = m.nc_log_id
INNER JOIN dbfastshosted.dbo.fh_sales_logs sl 
    on m.sales_id = sl.sales_id 
INNER JOIN dbfastsconfigdataref.dbo.cdf_terminal_user_account h 
    on cl.created_user_id = h.terminal_user_id
INNER JOIN dbfastsconfigdataref.dbo.cdf_terminal t 
    on h.terminal_id = t.terminal_id
INNER JOIN dbfastsconfigdataref.dbo.cdf_cuid c 
    on cl.cu_id = c.cu_id
WHERE YEAR(sales_timestamp)='2017' 
    and cl.currency_id = 2
    and c.card_type_id = '514'
GROUP BY terminal_name, DATENAME(MONTH,sales_timestamp), DATEPART(m,sales_timestamp)
ORDER BY DATEPART(m, sales_timestamp), terminal_nameerminal_name    

我希望以数据透视的形式提供数据。所以我将查询修改为:

WITH source_table (
    terminal_name
    ,Month_Name
    ,piece
    ,amount
    )
AS (
    SELECT DATENAME(MONTH, sales_timestamp) AS Month_Name
        ,COUNT(nc_deposit) AS piece
        ,ISNULL(sum(nc_deposit), 0) AS amount
        ,terminal_name
    FROM dbfastshosted.dbo.fh_mf_new_card_logs cl
    INNER JOIN dbfastshosted.dbo.fh_sales_map m ON cl.nc_log_id = m.nc_log_id
    INNER JOIN dbfastshosted.dbo.fh_sales_logs sl ON m.sales_id = sl.sales_id
    INNER JOIN dbfastsconfigdataref.dbo.cdf_terminal_user_account h ON cl.created_user_id = h.terminal_user_id
    INNER JOIN dbfastsconfigdataref.dbo.cdf_terminal t ON h.terminal_id = t.terminal_id
    INNER JOIN dbfastsconfigdataref.dbo.cdf_cuid c ON cl.cu_id = c.cu_id
    WHERE YEAR(sales_timestamp) = '2017'
        AND cl.currency_id = 2
        AND c.card_type_id = '514'
    GROUP BY DATENAME(MONTH, sales_timestamp)
        ,terminal_name
        ,DATEPART(m, sales_timestamp)
    ORDER BY DATEPART(m, sales_timestamp)
        ,terminal_name
    )
SELECT pieces.terminal_name
    ,pieces.January AS JanPcs
    ,amounts.January AS JanAmt
    ,pieces.February AS FebPcs
    ,amounts.February AS FebAmt
    ,pieces.March AS MarPcs
    ,amounts.March AS MarAmt
    ,pieces.April AS AprilPcs
    ,amounts.April AS AprilAmt
    ,pieces.May AS MayPcs
    ,amounts.May AS MayAmt
    ,pieces.June AS JunePcs
    ,amounts.June AS JuneAmt
    ,pieces.July AS JulyPcs
    ,amounts.July AS JulyAmt
    ,pieces.August AS AugustPcs
    ,amounts.August AS AugustAmt
    ,pieces.September AS SeptPcs
    ,amounts.September AS SeptAmt
    ,pieces.October AS OctPcs
    ,amounts.October AS OctAmt
    ,pieces.November AS NovPcs
    ,amounts.November AS NovAmt
    ,pieces.December AS DecPcs
    ,amounts.December AS DecAmt
FROM (
    SELECT *
    FROM (
        SELECT terminal_name
            ,Month_Name
            ,piece
        FROM source_table
        ) AS src_pieces
    PIVOT(MAX(piece) FOR Month_Name IN (
                January
                ,February
                ,March
                ,April
                ,May
                ,June
                ,July
                ,August
                ,September
                ,October
                ,November
                ,December
                )) AS pvt_pieces
    ) AS pieces
INNER JOIN (
    SELECT *
    FROM (
        SELECT terminal_name
            ,Month_Name
            ,amount
        FROM source_table
        ) AS src_pieces
    PIVOT(MAX(amount) FOR Month_Name IN (
                January
                ,February
                ,March
                ,April
                ,May
                ,June
                ,July
                ,August
                ,September
                ,October
                ,November
                ,December
                )) AS pvt_pieces
    ) AS amounts ON (amounts.terminal_name = pieces.terminal_name)

输出应该是这样的:

  terminal_name    JanAmt   JanPcs .... DecAmt   DecPcs
 ------------------------------------------------------------
  terminal A       1000     100          2000     200          

但是,我收到了这个错误

  

ORDER BY子句在视图,内联函数中派生无效   表,子查询和公用表表达式,除非TOP,OFFSET   或者也指定了FOR XML。

我多次尝试解决这个问题,但我没有任何想法。你们可以看看这个吗?谢谢!

2 个答案:

答案 0 :(得分:0)

CTE不能有ORDER BY。

您可以使用:

WITH CTE AS:

您的查询

SELECT * FROM CTE ORDER BY ...

答案 1 :(得分:0)

条件聚合不会更简单吗?

SELECT terminal_name
       sum(case when month(sales_timestamp) = 1 then nc_deposit else 0 end) as jan_amount,
       sum(case when month(sales_timestamp) = 2 then nc_deposit else 0 end) as feb_amount,
       . . .
       sum(case when month(sales_timestamp) = 12 then nc_deposit else 0 end) as dec_amount
FROM dbfastshosted.dbo.fh_mf_new_card_logs cl INNER JOIN
     dbfastshosted.dbo.fh_sales_map m
     on cl.nc_log_id = m.nc_log_id INNER JOIN 
     dbfastshosted.dbo.fh_sales_logs sl
     on m.sales_id = sl.sales_id INNER JOIN 
     dbfastsconfigdataref.dbo.cdf_terminal_user_account h 
     on cl.created_user_id = h.terminal_user_id INNER JOIN 
     dbfastsconfigdataref.dbo.cdf_terminal t
     on h.terminal_id = t.terminal_id INNER JOIN 
     dbfastsconfigdataref.dbo.cdf_cuid c
     on cl.cu_id = c.cu_id
WHERE YEAR(sales_timestamp) = 2017 AND
      cl.currency_id = 2 AND
      c.card_type_id = 514
GROUP BY terminal_name
ORDER BY terminal_name ;

这似乎比使用CTE,多个子查询和其他JOIN的多部分查询简单得多。

请注意,我从'2017'删除了单引号。 YEAR()函数返回一个数字,因此比较应该是一个数字。同样,我假设card_type_id是一个数字,而不是一个字符串。