【问题标题】:Total sum wrong value in Dynamic PivotDynamic Pivot 中的总和错误值
【发布时间】:2015-09-05 11:52:35
【问题描述】:

我有复杂的查询,效果很好(MS SQL 2012)。但是在总结相同价格的项目时会出错。它正确计算它们,但只计算一次价格,而不是将它们作为计数。它仅在同一商品具有相同价格且来自同一国家/地区时出现。这是我的查询;

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

这是结果;

如您所见,“俄罗斯”有 2 个“游戏机”,它需要正确计数 (2x),但只需要 1 个价格“151 美元”(通常必须是 302 美元)。如何在不对查询进行重大更改的情况下解决此问题?谢谢。

【问题讨论】:

  • 我快速检查了您的查询,我认为问题出在 Pivoting 之前。如果对我来说违反直觉,则将第二次存储在项目 x 总价的一列中。当我看到 2x 302 我想每 302 美元有 2 件商品而不是 2 件总成本为 302 的商品时,您不能将商品编号/价格总和存储在每个产品和总计的两列单独的列中吗?
  • 您使用的是哪个版本的 SQL Server?
  • @lad2025 是的 2x 表示商品数量的计数,而不是每个价格。我需要将这些值放在一张表中。

标签: sql sql-server sum pivot distinct


【解决方案1】:

我认为这可以满足您的需求。问题出在您的第一个 CTE 中,您在其中进行项目计数并在 ItemName、CountryName 和 Price 上获得不同的值。

按照如下所示进行分组并求和价格,而不是得到一个独特的。

    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

编辑: 以下是我得到的结果:

这是您从 CTE 开始的所有代码:

;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

【讨论】:

  • 现在它给出了“604$”和其他错误的值?
  • 我添加了我得到的结果和整个代码块。我的结果中没有看到 604 美元。
猜你喜欢
  • 1970-01-01
  • 2018-08-10
  • 1970-01-01
  • 2014-03-20
  • 2023-02-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-30
相关资源
最近更新 更多