将一个表多次连接到其他表

时间:2009-06-10 10:31:22

标签: sql

我有三张桌子:

表用户(userid用户名)

表键(userid keyid)

表笔记本电脑(userid laptopid)

我希望所有拥有密钥或笔记本电脑或两者兼有的用户。我如何编写查询,以便它使用表User和表Key之间的连接,以及表User和表Laptop之间的连接?

主要问题是在实际场景中,有十二个左右的表连接,如:

“选择..从左边的连接b开始(...),c连接d on(..),e,f,g where ...”,

我看到a可以加入b,a也可以加入f。所以假设我不能使表a,b和f并排出现,我该如何编写sql查询?

6 个答案:

答案 0 :(得分:9)

您可以使用多个联接来组合多个表:

select *
from user u
left join key k on u.userid = k.userid
left join laptop l on l.userid = u.userid

“左连接”还会找到没有钥匙或笔记本电脑的用户。如果用“内部联接”替换它们,它将只找到有笔记本电脑和密钥的用户。

当“左连接”找不到行时,它将在其字段中返回NULL。因此,您可以选择所有拥有笔记本电脑或密钥的用户:

select *
from user u
left join key k on u.userid = k.userid
left join laptop l on l.userid = u.userid
where k.userid is not null or l.userid is not null

NULL是特殊的,因为你将它比作“field is not null”而不是“field<> null”。

在你的评论后添加:说你有一个表鼠标,它与笔记本电脑有关,但与用户有关。您可以加入:

select *
from user u
left join laptop l on l.userid = u.userid
left join mouse m on m.laptopid = l.laptopid

如果这不能回答你的问题,你还需要澄清一点。

答案 1 :(得分:2)

-- // Assuming that a user can have at max 1 items of each type
SELECT      u.*
-- // Assuming that a user can have more then 1 items of each type, just add DISTINCT:
-- // SELECT      DISTINCT u.*
FROM        "User" u
LEFT JOIN   "Key"    u1 ON u.UserID = u1.UserID
LEFT JOIN   "Laptop" u2 ON u.UserID = u2.UserID
LEFT JOIN   "Server" u3 ON u.UserID = u3.UserID
-- // ...
WHERE       COALESCE(u1.UserID, u2.UserID, u3.UserID /*,...*/) IS NOT NULL

答案 2 :(得分:1)

select distinct u.userid, u.username
from User u 
    left outer join Key     /* k on u.userid = k.userid */
    left outer join Laptop  /* l on u.userid = l.userid */
where k.userid is not null or l.userid is not null

修改 “主要的问题是,在实际场景中,有十二个左右的表连接,如: “选择..从左边的连接b开始(...),c连接d on(..),e,f,g where ...”, 我看到a可以加入b,a也可以加入f。所以假设我不能使表a,b和f并排显示,我该如何编写sql查询?“

您可以根据需要使用多个左外连接。使用主键将表连接到其余表或任何其他字段,其中一个表的字段值应与其他表的字段值匹配。

例如,将比文字更好地解释

select * 
from a
 left outer join b on a.pk = b.fk -- a pk should match b fk
 left outer join c on a.pk = c.fk -- a pk should match c fk
 left outer join d on c.pk = d.fk -- c pk should match d fk

等等

答案 3 :(得分:1)

正如您所描述的那样,您只想知道某人是否有笔记本电脑或钥匙。我会用子查询而不是连接来编写查询:

select * 
from user 
where userid in (select userid from key union select userid from laptop)

这样做的原因是,通过联接,具有多个笔记本电脑或多个键的人将被列出多次(除非您使用distinct)。即使您使用distinct,最终也会得到效率较低的查询(至少在Oracle上,查询优化器似乎无法创建有效的计划)。

[编辑纠正Rashmi Pandit指出的内容。]

答案 4 :(得分:1)

解决方案一:

SELECT * FROM [User] u
INNER JOIN [Key] k
ON u.userid = k.userid

UNION

SELECT * FROM [User] u
INNER JOIN Laptop l
ON u.userid = l.userid

[...]

解决方案二:

SELECT * FROM [User] u
LEFT JOIN [Key] k
ON u.userid = k.userid
LEFT JOIN Laptop l
ON u.userid = l.userid
LEFT JOIN [...]
WHERE k.userid IS NOT NULL
OR l.userid IS NOT NULL
OR [...]

只是一个猜测,你也可以检查这两个的执行计划,看看UNION一个是否更重,反之亦然。

答案 5 :(得分:0)

 SELECT * 
 FROM User
 LEFT JOIN Key ON User.id = Key.user_id
 LEFT JOIN Laptop ON User.id = Laptop.user_id
 WHERE Key.id IS NOT NULL OR Laptop.id IS NOT NULL