select(投影)的列字段中的子查询如何与主查询的结果配对?形式:
SELECT id,email,(SELECT name From Names WHERE Names.id=Users.id) as name
FROM Users
Run Code Online (Sandbox Code Playgroud)
子查询是从 , 的输出中每行执行一次SELECT id,email FROM Users
,因此应该LIMIT 1
在子查询上使用(因为子查询中只有 1 行可以与主查询中的一行配对),还是子查询运行一次,并且然后每个结果都与来自 的相应行配对SELECT id,email FROM Users
,很像等效连接:SELECT id,email,name FROM Users JOIN Names ON Users.id=Names.id
在理想情况下,当 Names.id = Users.id 只返回 1 条记录时,两个查询相同。
当它不正确时的区别。
SELECT id,email,(SELECT name From Names WHERE Names.id=Users.id) as name
FROM Users
Run Code Online (Sandbox Code Playgroud)
将停止工作并返回错误,因此您需要添加 LIMIT 类
SELECT id,email,(SELECT name From Names WHERE Names.id=Users.id ORDER BY something LIMIT 1) as name
FROM Users
Run Code Online (Sandbox Code Playgroud)
同时查询
SELECT id,email,name FROM Users JOIN Names ON Users.id=Names.id
Run Code Online (Sandbox Code Playgroud)
继续工作而没有错误,此查询返回与用户相关的名称中的所有行
在其他一些情况下,当您只期望 1 个名称时,您将需要添加 GROUP BY 条件
SELECT id,email,name FROM Users JOIN Names ON Users.id=Names.id GROUP BY Users.id
Run Code Online (Sandbox Code Playgroud)
但是这种情况可能会从 Names 返回不可预测的名称(并且它不是 100% 的 SQL 合法构造),并且您再次需要使用派生表再添加 1 级 JOIN,并且有时它可能是丑陋的构造,
所以,你总是可以比较哪种形式的查询更适合所选案例,简单的例子:
SELECT t1.id,t1.email,t2.name FROM Users t1 JOIN
(SELECT id, name FROM Names n1 INNER JOIN
(SELECT MAX(dateregistered) as dateregistered, id FROM Names GROUP BY id) n2 ON n1.id=n2.id AND n1.dateregistered=n2.dateregistered) t2
ON t1.id = t2.id
Run Code Online (Sandbox Code Playgroud)
将返回与以下相同的结果:
SELECT id,email,(SELECT name From Names WHERE Names.id=Users.id ORDER BY dateregistered DESC LIMIT 1) as name
FROM Users
Run Code Online (Sandbox Code Playgroud)
添加:带有名称的示例看起来不现实,但实际情况 - 当您需要请求的不是名称(实际上是每人 1 个),而是具有 10 年历史的客户的实际邮政地址时。他可以有20个地址,你最需要回馈
根据我的经验,是的,您的子查询将为外部查询的每一行运行。
此外,由于您在子查询中没有使用任何形式的分组/聚合,因此无法保证查询将返回哪一行。
另一方面,查询最好这样写:
SELECT u.id,u.email,n.name
FROM Users u
JOIN Names n
ON n.id = u.id
Run Code Online (Sandbox Code Playgroud)
如下所述,如果表用户和表名称不保持真正的一对一关系。用户中的一行可能在名称中具有相同 id 的多行。如果是这种情况,您可以对查询进行以下更改来解决此问题。
SELECT u.id,u.email,n.name
FROM Users u
RIGHT JOIN Names n
ON n.id = u.id
WHERE u.id IS NOT NULL
LIMIT 1
Run Code Online (Sandbox Code Playgroud)
这将产生 Users 表中的每一行,这些行在 Names 表中拥有匹配的 id。但将响应限制为 1。请记住,如果没有 LIMIT 1,如果由于某种原因 Names 表中的多个条目具有相同的 id,这将列出重复的 u.emails。
归档时间: |
|
查看次数: |
53596 次 |
最近记录: |