2

重複の可能性:
Mysql:NOTEXISTSを実行します。パフォーマンスを向上させることは可能ですか?

それを行うためのより良い/最適な方法はありますか?exists代わりに使用する必要がありjoinますか?または2つの別々のクエリ?そして、一時テーブルについてはどうでしょうか。私はそれらについて読んでいましたが、不確かです。

グループからメンバーにメールを送信する。彼らがまだアイテムを受け取っていないことを確認します。

SELECT m.email,g.id 
FROM group g 
  LEFT JOIN  members m 
    ON  g.mid = m.id 
    AND g.gid='1' 
WHERE NOT EXISTS 
      ( SELECT id 
        FROM items AS i 
        WHERE i.mid=m.id 
        AND i.item_id='5'
      ) 
4

2 に答える 2

4

これは、JOINと同じものです。

SELECT m.email, g.id
From members m
JOIN group g ON g.mid = m.id AND g.gid = '1' 
LEFT JOIN items i ON i.mid = m.id AND i.item_id = '5'
WHERE i.id IS NULL

次の複合インデックスを使用します。

group (mid, gid)
items (mid, item_id)

グループではなくメンバーを返すように見えるため、メンバーとグループのLEFT JOINを逆にしました。また、そのグループのメンバーのみが必要なため、LEFTJOINをINNERJOINに変更しました。

私はこれがよりよく読むかもしれないと思います:

SELECT m.email, g.id
From members m
JOIN group g ON g.mid = m.id
LEFT JOIN items i ON i.mid = m.id AND i.item_id = 5
WHERE g.gid = 1
  AND i.id IS NULL

i.item_id = 5パーツをWHERE句に移動できるかどうか疑問に思われるかもしれません。i.id IS NULLとの行がないため、できませんi.item_id = 5。最初に結合を実行してから、WHERE句のNULL行を削除する必要があります。

于 2012-06-26T16:20:53.420 に答える
1

一時的なテーブルは必要ないと思います。許容できるパフォーマンスが得られない場合にのみ、実際にそのルートに進みます。

クエリから、次のようなスキーマを収集します。

group (id INT PK, gid INT, mid INT)
items (id INT PK, item_id INT, mid INT)
members (id INT PK, email VARCHAR)

あなたのテーブルは実際には「メンバーシップ」テーブルのように見えますgroup。これは、グループと個人の間の多対多の関係を解決/実装します。(つまり、人は0、1つ以上のグループのメンバーになることができます。グループは、ゼロ、またはそれ以上の人をメンバーとして持つことができます。)

groupとの間でLEFTJOINを使用していmembersます。これにより、一致するメンバーがない場合にグループの行が返され(group.idが返されます)、members.emailにはNULLが返されます(これは必要な場合があります)。ただし、メールアドレスのみを返したい場合は、これをINNERJOINに変更できます。

NOT EXISTS述部は、OUTER JOINと、JOINEDテーブルから返されたNULL値のテストに置き換えることができます。group.gidおよび/または列が数値データ型の場合items.item_id、述部の整数リテラルの前後から引用符を削除できます。

同等の結果セットを返し、パフォーマンスが向上する可能性のある代替案を次に示します。

SELECT m.email
     , g.id 
  FROM members m
  JOIN group g ON g.mid = m.id AND g.gid = 1
  LEFT
  JOIN items i ON i.mid = m.id AND i.item_id = 5
 WHERE i.id IS NULL

補遺:

items.item_id = 5テストケース(選択した回答のコメントで提供)は、ON句と句に述語があるクエリ間の結果セットの違いを示していWHEREます。(この述語をWHERE節に移動すると、反結合が混乱します。)

CREATE TABLE `group` (`id` INT PRIMARY KEY, `gid` INT, `mid` INT);
CREATE TABLE `items` (`id` INT PRIMARY KEY, `item_id` INT, `mid` INT);
CREATE TABLE `members` (`id` INT PRIMARY KEY, `email` VARCHAR(40));

INSERT INTO `group` VALUES (1,1,1), (2,1,2);
INSERT INTO `items` VALUES (1,5,1);
INSERT INTO `members` VALUES (1,'one@m.com'),(2,'two@m.com'); 
于 2012-06-26T17:50:33.597 に答える