select語句列中的MYSQL子查詢
select(投影)的列欄位中的子查詢如何與主查詢的結果配對?形式:
SELECT id,email,(SELECT name From Names WHERE Names.id=Users.id) as name FROM Users
子查詢是每行執行一次嗎
SELECT id,email FROM Users
,LIMIT 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
將停止工作並返回錯誤,因此您需要添加 LIMIT 類
SELECT id,email,(SELECT name From Names WHERE Names.id=Users.id ORDER BY something LIMIT 1) as name FROM Users
同時查詢
SELECT id,email,name FROM Users JOIN Names ON Users.id=Names.id
繼續工作而不會出現錯誤,此查詢返回與使用者相關的名稱中的所有行
在其他一些情況下,當您只期望 1 個名稱時,您需要添加 GROUP BY 條件
SELECT id,email,name FROM Users JOIN Names ON Users.id=Names.id GROUP BY Users.id
但是這種情況可能會從 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
將返回與以下相同的結果:
SELECT id,email,(SELECT name From Names WHERE Names.id=Users.id ORDER BY dateregistered DESC LIMIT 1) as name FROM Users
**添加:**帶有名稱的範例看起來不現實,但真實情況 - 當您需要的不是名稱(實際上是每人 1 個),而是具有 10 年曆史的客戶的實際郵政地址。他可以有 20 個地址,並且你需要返回最重新發送
以我的經驗是的,您的子查詢將為您的外部查詢的每一行執行。
此外,由於您沒有在子查詢中使用任何形式的分組/聚合,因此無法保證該查詢將返回哪一行。
另一方面,查詢最好這樣寫:
SELECT u.id,u.email,n.name FROM Users u JOIN Names n ON n.id = u.id
正如下面所指出的,如果表使用者和表名稱不保持真正的一對一關係。使用者中的一行可能在名稱中具有相同 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
這將為您生成使用者表中的每一行,它們在名稱表中擁有匹配的 id。但將響應限制為 1。請記住,如果沒有 LIMIT 1,這將列出重複的 u.email,如果出於某種原因,Names 表中的多個條目具有相同的 id。