Dynamic Pivot中的多个总计

时间:2015-02-28 16:10:53

标签: sql-server sql-server-2008 join sum dynamic-pivot

过去4天我一直在努力解决MSSQL Server查询问题。无论我尝试什么,我都失败了。如果有可能,我可以在这里得到。

这是我想从查询中获取的报告:

          Playstation    Laptop    Phone    Macbook    Total 
-------------------------------------------------------------
England    1x 257$       0x 0$     0x 0$     0x 0$    1x 257$
Sweden     0x 0$         1x 433$   1x 424$   0x 0$    2x 857$ 
Russia     2x 472$       0x 0$     0x 0$     0x 0$    2x 472$
Italy      0x 0$         0x 0$     0x 0$     0x 0$    0x 0$
Total      3x 729$       1x 433$   1x 424$   0x 0$    5x 1586$

这些是我的表格:

Country表:

Id   Name   
----------------------------------------
1     England
2     Sweden
3     Russia
4     Italy

Items表:

Id   Name   
----------------------------------------
1     Laptop
2     Phone
3     Playstation
4     Macbook

Pre-Request表:

Id   countryId   ItemId      blablabla
----------------------------------------
1        1         3          blablabla 
2        2         1          blablabla 
3        2         2          blablabla 
4        3         3          blablabla 
5        3         3          blablabla 
6        2         3          blablabla 

Offers表:

Id   Price         Blablabla
----------------------------------------
18     257$          Blablabla
19     151$          Blablabla
20     424$          Blablabla
21     433$          Blablabla
22     321$          Blablabla

Request表:

Id     preReqId     requestStatus     winOfferId
---------------------------------------------
44        1          3                   18
11        2          4                   21
53        3          4                   20
87        4          3                   22
43        5          3                   19
45        6          2                   Null

Blablabla列和行并不重要。只有报告表查询,我必须使用requestStatus > 2来获取合法报告,即使没有来自"意大利"或没有订购" Macbook"他们无论如何都会在报告中。谢谢

1 个答案:

答案 0 :(得分:2)

我插入临时表以使查询更具可读性。我在里面写了逻辑。

;WITH CTE AS
(
    SELECT DISTINCT I.NAME ITEMNAME,C.NAME COUNTRYNAME
    ,CAST(REPLACE(TAB.PRICE,'$','')AS INT)PRICE
    ,COUNT(CASE WHEN TAB.PRICE IS NOT NULL THEN I.NAME END) OVER(PARTITION BY C.NAME,I.NAME) CNTITEM    
    FROM [#Pre-Request] PR
    LEFT JOIN #Items I ON PR.ITEMID=I.ID
    LEFT JOIN #COUNTRY C ON PR.COUNTRYID = C.ID
    OUTER APPLY
    (
        SELECT R.preReqId,R.winOfferId,O.PRICE
        FROM #Request R 
        JOIN #Offers O ON R.winOfferId=O.Id
        WHERE PR.ID=R.preReqId
    )TAB

    UNION 
    -- Used to select Item name and country that are not in Pre-request table and other tables
    SELECT I.NAME ,C.NAME ,NULL,0
    FROM #Items I
    CROSS JOIN #COUNTRY C
)
,CTE2 AS
(
    -- Find the sum for number of items
    SELECT DISTINCT ISNULL(ITEMNAME,'TOTAL')ITEMNAME,ISNULL(COUNTRYNAME,'TOTAL')COUNTRYNAME,
    SUM(PRICE)PRICE 
    FROM CTE
    GROUP BY ITEMNAME,COUNTRYNAME
    WITH CUBE
)
,CTE3 AS
(
    -- Find the sum of PRICE
    SELECT DISTINCT ISNULL(ITEMNAME,'TOTAL')ITEMNAME,ISNULL(COUNTRYNAME,'TOTAL')COUNTRYNAME--,CNTITEM
    ,SUM(CNTITEM)CNTITEM    
    FROM 
    (
        SELECT DISTINCT ITEMNAME,COUNTRYNAME,CNTITEM
        FROM CTE
    )TAB
    GROUP BY ITEMNAME,COUNTRYNAME
    WITH CUBE
)
SELECT C2.*,C3.CNTITEM,
CAST(C3.CNTITEM AS VARCHAR(20))+'x'+' ' + CAST(C2.PRICE AS VARCHAR(20))+'$' NEWCOL
INTO #NEWTABLE
FROM CTE2 C2
JOIN CTE3 C3 ON C2.COUNTRYNAME=C3.COUNTRYNAME AND C2.ITEMNAME=C3.ITEMNAME

获取动态数据透视列

DECLARE @cols NVARCHAR (MAX)

SELECT @cols = COALESCE (@cols + ',[' + ITEMNAME + ']', '[' + ITEMNAME + ']')
               FROM (SELECT DISTINCT ITEMNAME FROM #NEWTABLE WHERE ITEMNAME<>'TOTAL') PV 
               ORDER BY ITEMNAME 
-- Since we need Total in last column, we append it at last
SELECT @cols += ',[Total]'

现在转动查询

DECLARE @query NVARCHAR(MAX)
SET @query = 'SELECT COUNTRYNAME,' + @cols + ' FROM 
             (
                 SELECT DISTINCT ITEMNAME,COUNTRYNAME,ISNULL(NEWCOL,''0x 0$'')NEWCOL
                 FROM #NEWTABLE
             ) x
             PIVOT 
             (
                 MIN(NEWCOL)
                 FOR ITEMNAME IN (' + @cols + ')
            ) p
            ORDER BY CASE WHEN (COUNTRYNAME=''Total'') THEN 1 ELSE 0 END,COUNTRYNAME' 

EXEC SP_EXECUTESQL @query