在唯一ID字段上连接表,每个Id值返回一个结果行

时间:2014-06-08 14:53:26

标签: sql sql-server join

我有几个表都有唯一的ID字段。我想在这个ID字段加入他们。更确切地说,我想从每个表中提取一列,并将所有提取的列与ID值对齐。这些表没有所有ID值的条目;我希望结果对于至少一个表中存在的每个ID值都有一行。如果其中一个表中缺少Id,则结果应为null。如果Id值在表中不唯一(在我的数据中,它们是),我不在乎会发生什么。

玩具示例:我有一个plant

Id  Name            Class
1   larch           pinopsida
3   horse chestnut  angiosperms

animal

Id  Name            Cry
1   cat             meow
2   dog             bow wow
4   carp            

mineral

Id  Name            Color
2   diamond         white
3   emerald         green

我希望将它们合并到

Id  Plant           Animal  Mineral
1   larch           cat     (null)
2                   dog     diamond
3   horse chestnut  (null)  emerald
4   (null)          carp    (null)

据我所知,这不是一个直的inner join,因为它只会保留所有数据库中存在的ID,也不会保留直接left joinright join因为那样只保留其中一个表中的Ids(没有一个表包含所有Id值),也不保留直接outer joincross join,因为这些会将ID传播到多行。

数据库是SQL Server 2012.我直接访问它,而不是通过其他编程语言。真正的查询是http://data.stackexchange.com/cs/query/36599/show-all-types - 除了列出所有可以相等的Id列对之外,还有更好的方法。

4 个答案:

答案 0 :(得分:1)

SELECT COALESCE(t.id, a.id, m.id) AS [ID]
     , MAX(t.name) AS Plant     
     , MAX(a.name) AS Animal
     , MAX(m.name) AS Mineral
FROM plant t FULL OUTER JOIN mineral m ON m.id = t.id
             FULL OUTER JOIN animal a ON a.id = t.id
GROUP BY COALESCE(t.id, a.id, m.id)
ORDER BY [ID]

Example

答案 1 :(得分:1)

您可以使用FULL JOIN

Select COALESCE(p.Id, a.Id, m.Id) Id
     , MAX(p.Name) Plant
     , MAX(a.Name) Animal
     , MAX(m.Name) Mineral
FROM   Plant p
       FULL JOIN Animal a ON p.Id = a.Id
       FULL JOIN Mineral m ON p.Id = m.Id
GROUP BY COALESCE(p.Id, a.Id, m.Id)
ORDER BY COALESCE(p.Id, a.Id, m.Id)

SQLFiddle demo


如果您不想在查询中使用COALESCEGROUP,则可以先获取ID并JOIN

WITH Ids AS (
  SELECT Id FROM Plant
  UNION
  SELECT Id FROM Animal
  UNION
  SELECT Id FROM Mineral
)
SELECT Ids.Id
     , p.Name Plant
     , a.Name Animal
     , m.Name Mineral
FROM   Ids
       LEFT JOIN Plant p ON Ids.Id = p.Id
       LEFT JOIN Animal a ON Ids.Id = a.Id
       LEFT JOIN Mineral m ON Ids.Id = m.Id

SQLFiddle demo

答案 2 :(得分:1)

或者你也可以有一个锚定表:

select anchor.Id, A.name, B.Name, C.Name
from
    (
        select distinct Id
        from (select Id from A union all select Id from B union all select Id from C) as T
    ) as anchor
    left outer join A on A.Id = anchor.Id
    left outer join B on B.Id = anchor.Id
    left outer join C on C.Id = anchor.Id

我忘记了在锚表中使ids明显不同但这非常重要。

答案 3 :(得分:-1)

select coalesce(A.Id, B.Id, C.Id) as Id, ...
from
    A
    full outer join B on B.Id = A.Id
    full outer join C on C.Id = A.Id or C.Id = B.Id

密钥处于ORed连接条件。它也可以写成C.Id = coalesce(A.Id,B.Id)

如果您的id值是各个表中的主键,则不需要在其他答案中使用的分组。