繁体   English   中英

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

[英]joining one table multiple times to other tables

我有三张桌子:

表用户(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查询?

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

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

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

-- // 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
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(...),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

等等

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

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

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

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

解决方案一:

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一个是否更重,反之亦然。

 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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM