2015-09-05 83 views
-1

我有复杂的查询,效果很好(MS SQL 2012)。但总结相同的价格项目时会出现错误。它对它们进行了正确的计数,但只需要花费一次,而不是将它们作为计数。只有当相同的商品具有相同的价格并来自同一国家时才会出现。这是我的问题;Dynamic Pivot中总计错误值

CREATE TABLE #ITEMS(ID INT,NAME VARCHAR(30)) 

INSERT INTO #ITEMS 
SELECT 1,  'laptop' 
UNION ALL 
SELECT 2,  'phone' 
UNION ALL 
SELECT 3,  'playstation' 
UNION ALL 
SELECT 4,  'MacBook' 

CREATE TABLE #Country(ID INT,NAME VARCHAR(30)) 

INSERT INTO #Country 
SELECT 1,  'England' 
UNION ALL 
SELECT 2,  'Sweden' 
UNION ALL 
SELECT 3,  'Russia' 
UNION ALL 
SELECT 4,  'Italy' 


CREATE TABLE [#Pre-Request](Id INT, countryId INT, ItemId INT) 

INSERT INTO [#Pre-Request] 
SELECT 1,1,3 
UNION ALL 
SELECT 2,2,1 
UNION ALL 
SELECT 3,2,2 
UNION ALL 
SELECT 4,3,3 
UNION ALL 
SELECT 5,3,3 
UNION ALL 
SELECT 6,2,3 

CREATE TABLE #Offers(Id INT, PRICE VARCHAR(50)) 

INSERT INTO #Offers 
SELECT 18,'257$' 
UNION ALL 
SELECT 19,'151$' 
UNION ALL 
SELECT 20,'424$' 
UNION ALL 
SELECT 21,'433$' 
UNION ALL 
SELECT 22,'151$' 

CREATE TABLE #Request(Id INT, preReqId INT, requestStatus INT,winOfferId INT) 

INSERT INTO #Request 
SELECT 44,  1,   3,     18 
UNION ALL 
SELECT 11,  2,   4,     21 
UNION ALL 
SELECT 53,  3,   4,     20 
UNION ALL 
SELECT 87,  4,   3,     22 
UNION ALL 
SELECT 43,  5,   3,     19 
UNION ALL 
SELECT 43,  6,   2,     Null 




;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 

这里是结果;

enter image description here

正如你可以看到有2个“游戏站”,从“俄罗斯”,就需要正确的次数(2次),但只取1价“151 $”(通常它必须是302 $)。我怎样才能解决这个问题,而不是从查询做重大更改?谢谢。

+0

我检查快速查询,我认为问题在于转轴之前。如果对我来说违反直觉,第二个存储在项目x总价格的一个列号中。当我看到'2x 302'时,我想象每个302 $ 2个项目,总成本302个项目不能包含2个项目,您不能将每个产品和总数的项目编号/价格总和分成两列分开列吗? – lad2025

+0

您正在使用哪个版本的SQL Server? – jpw

+0

@jpw MS SQL 2012 – TeknobilSoft

回答

2

我认为这是做你想做的。问题出在你的第一个CTE上,你需要进行项目计数,并在ItemName,CountryName和Price上得到一个明确的结果。

而不是得到一个独特的,做一个组,如下所示和SUM的价格。

SELECT I.NAME ITEMNAME, C.NAME COUNTRYNAME 
,SUM(CAST(REPLACE(TAB.PRICE,'$','')AS INT))PRICE 
,COUNT(CASE WHEN TAB.PRICE IS NOT NULL THEN 1 ELSE NULL END) 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 
GROUP BY 
    I.NAME 
    ,C.NAME 

编辑: 这里是我得到的结果:

enter image description here

这里是所有的代码从热膨胀系数开始的:

;WITH CTE AS 
(
    SELECT I.NAME ITEMNAME, C.NAME COUNTRYNAME 
    ,SUM(CAST(REPLACE(TAB.PRICE,'$','')AS INT))PRICE 
    ,COUNT(CASE WHEN TAB.PRICE IS NOT NULL THEN 1 ELSE NULL END) 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 
    GROUP BY 
     I.NAME 
     ,C.NAME 

    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 
+0

现在它给“604 $”和其他值出错了? – TeknobilSoft

+0

我添加了我得到的结果和整个代码块。我没有看到$ 604在我的结果中回来。 – PeterDNCO

+0

工作很好,非常感谢你的先生! – TeknobilSoft