过去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"他们无论如何都会在报告中。谢谢
答案 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