2つのテーブルが別のテーブルで関連付けられています(多対多)
これはスキーマの抜粋です。
CREATE TABLE user (
user_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
email TEXT NOT NULL UNIQUE
);
CREATE TABLE alias (
alias_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
address TEXT NOT NULL UNIQUE
);
CREATE TABLE alias_member (
alias_id INTEGER NOT NULL,
user_id INTEGER NOT NULL,
PRIMARY KEY(alias_id, user_id),
FOREIGN KEY(alias_id) REFERENCES alias(alias_id) ON DELETE CASCADE,
FOREIGN KEY(user_id) REFERENCES user(user_id) ON DELETE CASCADE
);
私のニーズを満たすこのクエリがあります。
SELECT email
FROM
user,
alias,
alias_member
WHERE
user.user_id = alias_member.user_id
AND alias.alias_id = alias_member.alias_id
AND alias.address = '[email protected]';
友人が私にも機能する別のクエリを提案しましたが、わかりません。
SELECT
email
FROM
user
INNER JOIN
(alias INNER JOIN alias_member ON alias.alias_id = alias_member.alias_id) ON user.user_id = alias_member.user_id
WHERE address='[email protected]';
誰か私に説明してくれませんか?
お使いのバージョンでは、1989年のように、ANSI-89標準のvery古いJOIN
構文を使用しています。1992年に、標準は次のように更新されましたJOIN...ON
構文を採用します。違いとその採用については、この SOの質問 で読むことができます。
テーブルをFROM
にリストしてからWHERE
に条件をリストする場合の問題は、どこかで条件を忘れることが非常に簡単なことです。誤って書くのはどれほど簡単でしょう。
SELECT email
FROM
user,
alias,
alias_member
WHERE
user.user_id = alias_member.user_id
AND alias.address = '[email protected]';
さて、あなたの友達のバージョンも奇妙な規則を使用しています( "ネストされた" JOIN
)。ここでは、JOIN
の最後のテーブルとしてalias_member
があるという事実を支援しようとしていますが、他の2つのテーブルを接続するために必要です。 alias_member
が最初のテーブルである場合、構文は少しわかりやすくなります。
SELECT
email
FROM
alias_member
INNER JOIN
user
ON alias_member.user_id = user.user_id
INNER JOIN
alias
ON alias_member.alias_id = alias.alias_id
WHERE address='[email protected]';
これは実際には別のクエリではありません。何が起こっているかをより明確にするために、既存のクエリを書き換えたものです。
コンマで区切られた3つのテーブルのリストを持つ元のFROM
句は、実際には3つのテーブルの暗黙的なINNER JOIN
であり、JOIN
の基準がWHERE
句で指定されています。一般に、JOIN
sを明示的にして、JOIN
sの条件を結合のON句に含める方が、より適切なコーディングと見なされます。これにより、テーブルがどのように組み合わされるかを理解しやすくなります。
JOIN
に固有ではない1つの基準は、WHERE
句に残されます。これは、さまざまなテーブルがどのように関連付けられているかに基づいてデータを制限するのではなく、関係に関係なく1つのテーブル内のフィールドの照合に基づいています。