10

私の MySQL データベースには 2 つのテーブルがあります。1 つはデータベース内のすべての書籍のライブラリで、もう 1 つはユーザーのライブラリにある書籍に対応する個々の行を含んでいます。

例えば:

ライブラリ テーブル

 `id`        `title`...
=====        ===========
  1          Moby Dick
  2          Harry Potter

コレクションテーブル

 `id`        `user`      `book`
=====        ======      =======
  1            1            2
  2            2            2
  3            1            1

私がやりたいことは、ユーザーのコレクションに含まれていないすべての本を表示するクエリを実行することです。このクエリを実行して、どのユーザーのコレクションにも含まれていないすべての本を表示できます。

SELECT * 
FROM  `library` 
LEFT OUTER JOIN  `collection` ON  `library`.`id` =  `collection`.`book` 
WHERE  `collection`.`book` IS NULL

私が知る限り、これはうまく機能します。これを PHPMyAdmin で実行すると、コレクション テーブルにないすべての書籍が表示されます。

ただし、それを特定のユーザーに制限するにはどうすればよいですか? たとえば、上記のダミー データでは、ユーザーがクエリを実行すると書籍 1 が返され、ユーザー2がクエリを実行すると書籍は返されません1

a を追加するだけでは機能しません。ステートメントAND user=[id]に関する知識が非常に限られてJOINいるため、実際にはどこにも行きません。

また、返される結果のID(表示されているクエリの、私が望むことはしませんが機能します)は0です-返されたIDがのIDであることを確認するにはどうすればよいlibrary.idですか?

4

2 に答える 2

15

LEFT JOIN特定のユーザーが持っている本だけに選択を絞り込む必要があります。結合されたテーブルあるものはすべてNULL、ユーザーがコレクションに持っていない行 (本) になります。

SELECT
    a.id,
    a.title
FROM
    library a
LEFT JOIN
    (
        SELECT book
        FROM collection
        WHERE user = <userid>
    ) b ON a.id = b.book
WHERE 
    b.book IS NULL

別の方法は次のとおりです。

SELECT
    a.id,
    a.title
FROM
    library a
WHERE 
    a.id NOT IN
    (
        SELECT book
        FROM collection
        WHERE user = <userid>
    )

NOT INただし、MySQL はクエリ全体に対して 1 回だけではなく、行ごとに 1 回サブクエリを実行するため、最初のソリューションの方が最適です。直感的には、MySQL がサブクエリを 1 回実行し、それをリストとして使用することを期待しますが、MySQL は相関サブクエリと非相関サブクエリを区別するほどスマートではありません。

ここで述べたように:

「問題は、IN サブクエリを使用するステートメントの場合、オプティマイザがそれを相関サブクエリとして書き換えることです。」

于 2012-06-15T21:20:39.840 に答える
4

これはどう?それは私の頭のてっぺんから外れています-現在、テストするデータベースにアクセスできません。(ごめん)

SELECT 
   * 
FROM 
   library lib 
WHERE 
   lib.id NOT IN (
      SELECT 
         book 
      FROM 
         collection coll 
      WHERE 
         coll.user =[id]
   )
;
于 2012-06-15T21:30:37.577 に答える