与使用单个内部联接相比,使用多个内部联接时我得到不同的结果

When using multiple inner joins I get different results compared to when I use a single inner join

我无法理解为什么我的两个 SQL 查询输出了不同的高级管理人员计数结果,而我预计它们是相同的。

SELECT COMPANY.Company_Code, COMPANY.Founder, COUNT(SENIOR_MANAGER.Senior_Manager_Code)
FROM COMPANY INNER JOIN SENIOR_MANAGER
ON SENIOR_MANAGER.COMPANY_CODE = COMPANY.COMPANY_CODE
GROUP BY COMPANY.COMPANY_CODE, COMPANY.FOUNDER;

这个SQL查询试图找出不同公司有多少高级经理,结果如下:

C1 Angela 5 
C10 Earl 2 
C100 Aaron 4 
C11 Robert 1 
C12 Amy 6 

但是,当我在使用两个内部联接的另一个查询中使用相同的条件时,我得到了另一组结果。这是我的查询:

SELECT COMPANY.COMPANY_CODE, COMPANY.FOUNDER, COUNT(LEAD_MANAGER.LEAD_MANAGER_CODE), 
COUNT(SENIOR_MANAGER.SENIOR_MANAGER_CODE)
FROM COMPANY INNER JOIN LEAD_MANAGER
ON COMPANY.COMPANY_CODE = LEAD_MANAGER.COMPANY_CODE
INNER JOIN SENIOR_MANAGER
ON SENIOR_MANAGER.COMPANY_CODE = COMPANY.COMPANY_CODE
GROUP BY COMPANY.COMPANY_CODE, COMPANY.FOUNDER;

结果如下:

C1 Angela 10 10 
C10 Earl 2 2 
C100 Aaron 8 8 
C11 Robert 1 1 
C12 Amy 12 12

第四列是高级管理人员的数量,由于某种原因与第三列的值相同,但与我显示的第一个查询的值不同。有人可以解释为什么结果不同吗?我怀疑这可能是因为我错误地使用了内部联接?

我期望的结果是第四列显示第一个查询的值。

每次加入新的table,结果集中的每一行都乘以该行在新的table中匹配加入条件的次数。

所以你的结果显示 C1、C100 和 C12 中的每一个都有两个 LEAD_MANAGERs。

由于双连接查询的计数反映了单连接查询的倍数,因此您重复计算了以前与新连接不同的配对。

具体来说,在第一个查询中,COMPANYSENIOR_MANAGER table 可以具有一对多关系,其中一个不同的公司可以有多个高级经理。

然而,在第二个查询中,当包含 LEAD_MANAGER table 时,它与 COMPANY 有更多不同的配对,您为每个对应的配对重复 SENIOR_MANAGER 多次COMPANYLEAD_MANAGER.


作为重复计算的解决方案,考虑加入聚合子查询(或CTEs):

SELECT agg_s.COMPANY_CODE,
       agg_s.FOUNDER,
       agg_s.SENIOR_MANAGER_COUNT.
       agg_l.LEAD_MANAGER_COUNT
FROM
  (SELECT c.COMPANY_CODE, 
          c.FOUNDER, 
          COUNT(s.SENIOR_MANAGER_CODE) AS SENIOR_MANAGER_COUNT
   FROM COMPANY c
   INNER JOIN SENIOR_MANAGER s
      ON s.COMPANY_CODE = c.COMPANY_CODE
   GROUP BY c.COMPANY_CODE,
            c.FOUNDER
  ) AS agg_s
INNER JOIN
  (SELECT c.COMPANY_CODE, 
          c.FOUNDER, 
          COUNT(l.LEAD_MANAGER_CODE) AS LEAD_MANAGER_COUNT
   FROM COMPANY c
   INNER JOIN LEAD_MANAGER l
      ON c.COMPANY_CODE = l.COMPANY_CODE
   GROUP BY c.COMPANY_CODE,
            c.FOUNDER
  ) AS agg_l

ON  agg_s.COMPANY_CODE = agg_l.COMPANY_CODE
AND agg_s.FOUNDER = agg_l.FOUNDER

更好的是,考虑 table 设计更改以实现适当的规范化,您可以在其中维护 单个 MANAGER table 和 TYPE SENIORLEAD 的指示符列。然后运行一个单个条件聚合查询:

SELECT c.COMPANY_CODE, 
       c.FOUNDER, 
       COUNT(CASE WHEN m.TYPE = 'SENIOR' THEN 1 ELSE NULL END) AS SENIOR_MANAGER_COUNT,
       COUNT(CASE WHEN m.TYPE = 'LEAD' THEN 1 ELSE NULL END) AS LEAD_MANAGER_COUNT
FROM COMPANY c
INNER JOIN MANAGER m
   ON c.COMPANY_CODE = m.COMPANY_CODE
GROUP BY c.COMPANY_CODE,
         c.FOUNDER;