web-dev-qa-db-ja.com

SELECTステートメントの列のMYSQLサブクエリ

選択(投影)の列フィールドのサブクエリは、メインクエリの結果とどのようにペアになっていますか?次の形式で:

 SELECT id,email,(SELECT name From Names WHERE Names.id=Users.id) as name
 FROM Users

サブクエリはSELECT id,email FROM Usersの出力から行ごとに1回実行されます。したがって、サブクエリでLIMIT 1を使用する必要があります(メインクエリの行とペアにできるのはサブクエリの1行だけなので) )、またはサブクエリが1回実行され、各結果は、同等の結合と同様に、SELECT id,email FROM Usersの対応する行とペアになります:SELECT id,email,name FROM Users JOIN Names ON Users.id=Names.id

5
Daniel Valland

理想的な状況では、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から予期しない名前を返す可能性があり(SQLの100%正当な構成ではありません)、派生テーブルを使用してさらに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人につき1つではなく、10年の歴史を持つクライアントの実際の住所です。彼は20のアドレスを持つことができ、あなたはほとんどの再送を返す必要があります

4
a_vlad

私の経験では、はい、サブクエリは外部クエリのすべての行に対して実行されます。

また、サブクエリでグループ化/集計の形式を使用していないため、そのクエリが返す行については保証されません。

一方、そのクエリは次のように記述した方がよいでしょう。

SELECT u.id,u.email,n.name
FROM Users u
JOIN Names n
    ON n.id = u.id

以下で指摘するように、テーブルユーザーとテーブル名が真の1対1の関係を保持していない場合。ユーザーの行が同じ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

これにより、Namesテーブルに一致するIDを持つ、Usersテーブルのすべての行が得られます。ただし、応答を1に制限します。LIMIT1がないと、何らかの理由でNamesテーブルの複数のエントリが同じIDを持つ場合に、重複するu.emailがリストされることに注意してください。

0
DarbyM