我有三张桌子:
表用户(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查询?
答案 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