没有关系的联接多个表

问题描述

我需要连接3个表,这些表之间没有关系,除了它们都有共同的字段(profiledid和instanceid) 例如,这3个表分别是成就[0条记录],附件[6条记录]和大学学习[4条记录]

如果我使用内部联接,它将执行笛卡尔积,我将获得24条记录,

SELECT a.*,v.*,c.* FROM dbo.Profile p 
LEFT JOIN Achievement v ON p.id = v.ProfileId AND v.InstanceId = 6559
LEFT JOIN Attachment a ON p.id = a.ProfileId AND a.InstanceId = 6559
LEFT JOIN CollegeAttended c ON p.id = c.ProfileId AND c.InstanceId = 6559
WHERE p.Id = 5574443

但是,我只需要获得6条记录即可。

我写了这个查询,得到了6条记录。但是,如果驱动表(在此查询附件中)具有最大的行数,则此查询将运行良好。

SELECT t1.*,t2.*,t3.* 
FROM (SELECT a.*,ROW_NUMBER() OVER (ORDER BY id) AS rn
    FROM Attachment a
    WHERE a.ProfileId = 5574443 AND a.InstanceId = 6559) AS t1
LEFT OUTER JOIN (
    SELECT b.*,ROW_NUMBER() OVER (ORDER BY id) AS rn
    FROM Achievement b
    WHERE b.ProfileId = 5574443 AND b.InstanceId = 6559) AS t2 ON t1.rn = t2.rn
LEFT OUTER JOIN (
    SELECT c.*,ROW_NUMBER() OVER (ORDER BY id) AS rn
    FROM CollegeAttended c
    WHERE c.ProfileId = 5574443 AND c.InstanceId = 6559) AS t3 ON t1.rn = t3.rn

如果附件有0条记录,则此查询将不返回任何记录。

有没有一种方法可以编写查询以执行所需的操作

谢谢

解决方法

描述问题时,可以使用full outer join

SELECT t1.*,t2.*,t3.* 
FROM (SELECT a.*,ROW_NUMBER() OVER (ORDER BY id) AS rn
      FROM Attachment a
      WHERE a.ProfileId = 5574443 AND a.InstanceId = 6559
     ) t1 FULL JOIN
     (SELECT b.*,ROW_NUMBER() OVER (ORDER BY id) AS rn
      FROM Achievement b
      WHERE b.ProfileId = 5574443 AND b.InstanceId = 6559
     ) t2
     USING (rn) FULL JOIN
     (SELECT c.*,ROW_NUMBER() OVER (ORDER BY id) AS rn
      FROM CollegeAttended c
      WHERE c.ProfileId = 5574443 AND c.InstanceId = 6559
     ) t3 
     USING (rn);

尽管FULL JOINUSING都是标准SQL,但并非所有数据库都支持它们。

,

如果数据库支持该功能,则可以切换到full join。如果您的数据库不支持using,这有点棘手,但是您可以:

SELECT t1.*,ROW_NUMBER() OVER (ORDER BY id) AS rn
    FROM Attachment a
    WHERE a.ProfileId = 5574443 AND a.InstanceId = 6559
) AS t1
FULL JOIN (
    SELECT b.*,ROW_NUMBER() OVER (ORDER BY id) AS rn
    FROM Achievement b
    WHERE b.ProfileId = 5574443 AND b.InstanceId = 6559
) AS t2 ON t1.rn = t2.rn
FULLL JOIN (
    SELECT c.*,ROW_NUMBER() OVER (ORDER BY id) AS rn
    FROM CollegeAttended c
    WHERE c.ProfileId = 5574443 AND c.InstanceId = 6559
) AS t3 ON COALESCE(t1.rn,t2.rn) = t3.rn