web-dev-qa-db-ja.com

多対多の関係に対するSELECTクエリの説明が必要

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]';

誰か私に説明してくれませんか?

5
oneohthree

お使いのバージョンでは、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]';
4
Steven Hibble

これは実際には別のクエリではありません。何が起こっているかをより明確にするために、既存のクエリを書き換えたものです。

コンマで区切られた3つのテーブルのリストを持つ元のFROM句は、実際には3つのテーブルの暗黙的なINNER JOINであり、JOINの基準がWHERE句で指定されています。一般に、JOINsを明示的にして、JOINsの条件を結合のON句に含める方が、より適切なコーディングと見なされます。これにより、テーブルがどのように組み合わされるかを理解しやすくなります。

JOINに固有ではない1つの基準は、WHERE句に残されます。これは、さまざまなテーブルがどのように関連付けられているかに基づいてデータを制限するのではなく、関係に関係なく1つのテーブル内のフィールドの照合に基づいています。

2
RDFozz