【问题标题】:SQL Join Duplicating Totals in Certain RowsSQL 联接在某些行中重复总计
【发布时间】:2021-08-06 15:15:22
【问题描述】:

尝试连接两个表以显示匹配的总计,但是连接(或分组依据)正在为一些记录(不是全部)创建不正确的总和。我分别检查了这两个表,以确保支付+税的总数匹配,并且在单独的表中查看时它们会这样做。似乎正在发生的是一些“total1”记录被乘以 2(不知道为什么)。

表1:

pnum branch year total
5678 efgh 2018 2000
5678 efgh 2018 2579

表2:

pnum branch year paid tax
5678 efgh 2018 3200 900
5678 efgh 2018 400 79

代码:

Select pnum, a.branch, a.year, sum(total) as total, sum(paid+tax) as total1
from ##table1 a
inner join ##table2 b

on a.[pnum] = b.pnum2 and a.year = left(b.year,4) and a.branch = b.branch
Group by pnum, a.branch, a.year

结果如下所示:

pnum branch year total total1
1234 abcd 2020 3520 3520
5678 efgh 2018 4579 9158
9101 ijkl 2019 2378 2378
1121 mnop 2019 9436 9436

如您所见,在第 2 行中,“total1”是“total”值的两倍……“total”和“total1”都应该匹配。

任何帮助/建议将不胜感激。

【问题讨论】:

  • 请提供样本数据。结果不正确并不明显。
  • 您好@2020db9,请检查第 2 行的支付和税收列值。可能存在错误值。
  • 很可能其中一个表有重复的行,可能是##table2。样本数据和预期结果将大有帮助。
  • 养成良好的习惯。每个列引用都应该包含适当的表别名(像“a”这样的别名也只是懒惰的习惯)。我们不知道哪个表包含哪个列,但您的逻辑似乎假设表之间存在 1:1 关系。否则不会有“重复”,你的总数是正确的。您也许可以将所有表联合起来,然后对该结果集求和 - 但如果没有 DDL 和样本数据,这是一个冒险的猜测。
  • 总和(已付+税)可能有问题吗?我编辑了我的初始帖子并包含了源数据的示例

标签: sql sql-server inner-join


【解决方案1】:

当关系不是一对一时,这是正常的连接行为。每个表中可能有多个匹配项。您可以通过多种方式做到这一点。这是一个分别对每个表求和然后加入结果的方法。这种关系(在 cte1 和 cte2 之间)现在是一对一的。我忽略了一个表中的条目可能在另一个表中不匹配的情况。

WITH cte1 AS (
        SELECT pnum, branch, year, SUM(total) AS total1
          FROM table1
         GROUP BY pnum, branch, year
     )
   , cte2 AS (
        SELECT pnum2 AS pnum, branch, year, SUM(paid+tax) AS total2
          FROM table2
         GROUP BY pnum2, branch, year
     )
SELECT cte1.pnum, cte1.branch, cte1.year, cte1.total1, cte2.total2
  FROM cte1
  JOIN cte2
    ON cte1.pnum   = cte2.pnum
   AND cte1.branch = cte2.branch
   AND cte1.year   = cte2.year
;

最终修正结果:

pnum    branch  year    total1  total2
5678    efgh    2018    4579    4579

@EdmCoff 提供的测试用例很有帮助。我对其进行了调整以显示您报告的行为,然后在小提琴底部添加了一个解决方案。

Working test case, edited from the comment of @EdmCoff

请注意,@EdmCoff 创建了一个初始测试用例,通过在插入之前手动聚合表数据来避免该问题。这基本上就是我们在最终解决方案中所做的,在每个 CTE 术语中。

【讨论】:

    【解决方案2】:

    使用UNION ALL 代替连接来获取 2 个表的所有行,然后聚合:

    SELECT pnum, branch, year,
           SUM(total) total,
           SUM(total1) total1
    FROM(
      SELECT pnum, branch, year, total, 0 total1 FROM table1
      UNION ALL
      SELECT pnum2, branch, LEFT(year, 4), 0, paid + tax FROM table2
    ) t
    GROUP BY pnum, branch, year
    

    请参阅demo

    【讨论】:

      猜你喜欢
      • 2017-01-03
      • 1970-01-01
      • 2015-09-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-01
      • 2021-12-24
      • 1970-01-01
      相关资源
      最近更新 更多