结果集上的SQL SUM(DISTINCT ...)

时间:2016-01-08 15:48:30

标签: sql sql-server

以下是两个表TBL1和TBL2

TBL1
ID1    Item    Val1     
100    Shirt    10      
101    Shirt    15      
102    Shirt    10      
100    Shirt    10      
100    Shirt    10      
103    Pants    14      

TBL2        

ID2    ID1    Val2
901    100    24
902    101    15
903    102    31
904    100    45
905    100    62
906    103    17

现在我在这两个表上执行以下查询:

SELECT TBL1.Item AS Item,
       Count(DISTINCT TBL1.ID1) AS Cpt,
       SUM (TBL1.Val1) AS Tot1,
       SUM (TBL2.Val2) AS Tot2
FROM TBL1, TBL2
WHERE TBL1.ID1 = TBL2.ID2
GROUP BY TBL1.Item

这里的问题是SUM(TBL1.Val1)不会考虑冗余值,即相同的TBL1.ID1。如果我使用SUM(DISTINCT TBL1.ID1), 一些信息不会被考虑在内。对于ID1 = 102,Val1 = 10将不会在SUM (DISTINCT TBL1.ID1)中使用。

您如何认为我可以重写该查询,以便SUM仅针对不同的ID1运行?结果如下:

Item    Cpt    Tot1    Tot2
Shirt    5      35      177
Pants    1      14      17

1 个答案:

答案 0 :(得分:3)

这就是我的意思:

DECLARE @TBL1 TABLE (
  ID1 INT
  , Item VARCHAR(10)
  , Val1 INT
  );

DECLARE @TBL2 TABLE (
  ID2 INT
  , ID1 INT
  , Val2 INT
  );

INSERT INTO @TBL1 (ID1, Item, Val1)
VALUES (100, 'Shirt', 10)
  , (101, 'Shirt', 15)
  , (102, 'Shirt', 10)
  , (100, 'Shirt', 10)
  , (100, 'Shirt', 10)
  , (103, 'Pants', 14);

INSERT INTO @TBL2 (ID2, ID1, Val2)
VALUES (901, 100, 24)
  , (902, 101, 15)
  , (903, 102, 31)
  , (904, 100, 45)
  , (905, 100, 62)
  , (906, 103, 17);

;WITH Items (ID1, Item, Val1)
AS (
  SELECT DISTINCT ID1, Item, Val1
  FROM @TBL1
  )
, Items2 (Item, Tot1) 
  AS (
  SELECT Item, SUM(Val1)
  FROM Items
  GROUP BY Item
  )
, TBL2 (ID1, Tot2)
  AS (
  SELECT ID1, SUM(Val2)
  FROM @TBL2
  GROUP BY ID1
  )
SELECT T.Item
  , COUNT(T1.ID1) AS Cpt
  , T.Tot1
  , SUM(DISTINCT T2.Tot2)
FROM Items2 AS T
INNER JOIN @TBL1 AS T1
  ON T1.Item = T.Item
INNER JOIN TBL2 AS T2
  ON T2.ID1 = T1.ID1
GROUP BY T.Item, T.Tot1;

它不是那么优雅,但它完成了工作。结果如下:

╔═══════╦═════╦══════╦══════╗
║ Item  ║ Cpt ║ Tot1 ║ Tot2 ║
╠═══════╬═════╬══════╬══════╣
║ Pants ║   1 ║   14 ║   17 ║
║ Shirt ║   5 ║   35 ║  177 ║
╚═══════╩═════╩══════╩══════╝

您可以在data.stackexchange.com

上运行查询

更新,添加没有CTE的查询:

SELECT T.Item
  , COUNT(T1.ID1) AS Cpt
  , T.Tot1
  , SUM(DISTINCT T2.Tot2) AS Tot2
FROM (
  SELECT Item, SUM(Val1) AS Tot1
  FROM (SELECT DISTINCT ID1, Item, Val1 FROM @TBL1) AS X
  GROUP BY X.Item
  ) AS T
INNER JOIN @TBL1 AS T1
  ON T1.Item = T.Item
INNER JOIN (
  SELECT ID1, SUM(Val2) AS Tot2
  FROM @TBL2
  GROUP BY ID1
  ) AS T2
  ON T2.ID1 = T1.ID1
GROUP BY T.Item, T.Tot1;

这也可以在data.stackexchange.com上运行

更新号码2

如果在运行SUM(DISTINCT T2.Tot2) AS Tot2时会出现一些欺骗,以前的查询可能会理论上提供错误的结果。这应该可以正常工作,虽然它需要额外的连接。

SELECT T1.Item
  , T3.Cpt
  , T1.Tot1
  , T2.Tot2
FROM (
  SELECT Item, SUM(Val1) AS Tot1
  FROM (SELECT DISTINCT ID1, Item, Val1 FROM @TBL1) AS X
  GROUP BY X.Item
  ) AS T1
INNER JOIN (
  SELECT T1.Item, SUM(Val2) AS Tot2
  FROM (SELECT DISTINCT ID1, Item, Val1 FROM @TBL1) AS T1
  INNER JOIN @TBL2 AS T2
    ON T2.ID1 = T1.ID1
  GROUP BY T1.Item
  ) AS T2
  ON T2.Item = T1.Item
INNER JOIN (
  SELECT Item, COUNT(*) AS Cpt
  FROM @TBL1
  GROUP BY Item
  ) AS T3
  ON T3.Item = T1.Item;