【问题标题】:How do I join 3 tables where a given ID may be present in one or more with only one row per ID?如何连接 3 个表,其中给定 ID 可能出现在一个或多个表中,每个 ID 只有一行?
【发布时间】:2021-07-30 20:11:01
【问题描述】:

我有 3 张桌子。

Table1 字段

  • 员工编号
  • 第 1 年销售额

Table2 字段

  • 员工编号
  • Year2Sales

Table3 字段

  • 员工编号
  • 第三年销售额

我想要的输出是一个表,每个 EmployeeId 一行。

输出表字段

  • 员工编号
  • 第 1 年销售额
  • Year2Sales
  • 第三年销售额

问题是给定的员工可能只出现在这些表之一中。我尝试使用如下的FULL JOIN,但如果所有 3 个表中都不存在,我会为每个员工获得多行。

SELECT COALESCE(T1.EmployeeId, T2.EmployeeId, T3.EmployeeId),
       Year1Sales,
       Year2Sales,
       Year3Sales,
FROM Table1 AS T1 FULL JOIN Table2 AS T2 ON T1.EmployeeId = T2.EmployeeId
                  FULL JOIN Table3 AS T3 ON T1.EmployeeId = T3.EmployeeId

Table1Table2Table3 中,每个EmployeeId 只有一行。

例如,如果员工只在第 2 年和第 3 年出现,我会得到以下错误输出:

EmployeeId     Year1Sales      Year2Sales     Year3Sales
1                NULL             1000           NULL
1                NULL             NULL           2000

如何将这 3 个表连接在一起并且每个员工只有一行?

【问题讨论】:

标签: sql sql-server tsql


【解决方案1】:

也许将他们全部加入所有员工 id 的并集:

WITH all AS(
  SELECT EmployeeId FROM T1 UNION SELECT EmployeeId FROM T2 UNION SELECT EmployeeId FROM T3 )

SELECT * 
FROM
  all
  LEFT JOIN T1 ON all.EmployeeId = T1.EmployeeID
  LEFT JOIN T2 ON all.EmployeeId = T2.EmployeeID
  LEFT JOIN T3 ON all.EmployeeId = T3.EmployeeID

如果 emp 将在一个表中出现多次,请在加入之前将它们分组:

FROM
  all
  LEFT JOIN (SELECT EmployeeID, SUM(Year1Sales) as Year1Sales FROM T1 GROUP BY EmployeeID) T1 ON all.EmployeeId = T1.EmployeeID
  ...

【讨论】:

  • 为什么要第二次查询表,似乎完全没有必要?
【解决方案2】:

还有另一种方法。

select EmployeeId, SUM(Year1Sales) As Year1Sales, SUM(Year2Sales) As Year2Sales, SUM(Year3Sales) As Year3Sales
from (
select EmployeeId, Year1Sales, Null Year2Sales, Null Year3Sales from Table1
union All
select EmployeeId, Null Year1Sales, Year2Sales, Null Year3Sales from Table2
union All
select EmployeeId, Null Year1Sales, Null Year2Sales, Year3Sales from Table3) As T
group by EmployeeId
order by EmployeeId;

【讨论】:

    【解决方案3】:

    您需要先合并第一个FULL JOIN,然后才能加入第三个表

    SELECT
      ISNULL(T1.EmployeeId, T3.EmployeeId) EmployeeId,
      T1.Year1Sales,
      T1.Year2Sales,
      T3.Year3Sales
    FROM (
        SELECT
          ISNULL(T1.EmployeeId, T2.EmployeeId) EmployeeId,
          T1.Year1Sales,
          T2.Year2Sales
        FROM Table1 AS T1
        FULL JOIN Table2 AS T2 ON T1.EmployeeId = T2.EmployeeId
    ) T1
    FULL JOIN Table3 AS T3 ON T1.EmployeeId = T3.EmployeeId;
    

    这里发生的是连接条件没有被满足

    ON T1.EmployeeId = T3.EmployeeId
    

    发生的情况是 T1 没有匹配的 ID,所以 T3 正在被不匹配的推送。

    您可以使用ON T3.EmployeeId IN (T1.EmployeeId, T2.EmployeeId),它看起来更简单,但通常性能更差。

    db<>fiddle

    我注意到,在三个单独的表中具有相似的数据本身就是一个设计问题。应该是一张大桌子。

    【讨论】:

      猜你喜欢
      • 2014-09-30
      • 2014-07-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-06
      • 1970-01-01
      • 2022-01-07
      • 1970-01-01
      相关资源
      最近更新 更多