16

現在、データベースに2つのmysqlテーブルがあります

FilmFilm_Ratings_Report

Film の主キーは、テーブルfilmid内の映画の評価を識別するために使用されるものです。Film_Ratings_Report

MYSQL クエリを使用して評価テーブルのみを検索し、特定の基準に適合するすべての映画 ID を収集してから、選択した ID を使用して映画テーブルから映画のタイトルを取得できるかどうかを知りたいです。以下は、動作していない MYSQL クエリ Im です。

SELECT * 
FROM film 
UNION SELECT filmid 
      FROM film_rating_report 
      WHERE rating = 'GE' 
      LIMIT 0,0

私はMYSQLに比較的慣れていないので、これについて何か助けていただければ幸いです。

前もって感謝します

4

5 に答える 5

16
SELECT * FROM film WHERE id IN 
  (SELECT filmid FROM film_rating_report WHERE rating = 'GE');

動作するはずです

于 2013-07-01T08:12:29.183 に答える
16

2 つの結合されたテーブルの 1 つからのデータのみが必要な結合など、準結合が必要なようですこの場合、必要な条件 ( ) を持つfilm一致する行があるすべての行。film_rating_reportrating = 'GE'

'GE'2 番目のテーブルに 2 つ (またはそれ以上) の行 (映画の 2 つの評価、両方とも) がある場合でも、映画を 2 回 (またはそれ以上) ではなく 1 回表示する必要があるため、これは通常の結合とまったく同じではありません。回) 通常の結合で示されるように。

半結合を記述するにはさまざまな方法があり、最も一般的なものは次のとおりです。

  • EXISTS相関サブクエリを使用する( @Justin's answer ):

    SELECT t1.* 
    FROM film t1 
    WHERE EXISTS (SELECT filmid 
                  FROM film_rating_report t2
                  WHERE t2.rating = 'GE'
                  AND t2.filmid = t1.id);
    
  • (無相関) サブクエリを使用するIN( @SG 86 の回答): (これは、結合する列 (この場合は 2 つ) が Nullableの場合
    、予期しない結果を返すか、まったく返さない可能性があるため、細心の注意を払って使用する必要があります)filmid

    SELECT * 
    FROM film 
    WHERE id IN 
      ( SELECT filmid 
        FROM film_rating_report 
        WHERE rating = 'GE'
      );
    
  • 結果の重複行を避けるために通常のJOINaを使用する ( @Tomas の回答) : DBMS では、すべての列を含める必要があります: ) GROUP BY
    GROUP BYGROUP BY f.filmid, f.title, f.director, ...

    SELECT f.*
    FROM film AS f
        JOIN film_rating_report AS frr
             ON f.filmid = frr.filmid
    WHERE frr.rating = 'GE' 
    GROUP BY f.filmid ;
    
  • @Tomasの回答のバリエーション。GROUP BY派生テーブルで行われ、次にJOIN

    SELECT f.*
    FROM film AS f
        JOIN 
            ( SELECT filmid
              FROM film_rating_report
              WHERE rating = 'GE'
              GROUP BY filmid
            ) AS frr
          ON f.filmid = frr.filmid ;
    

どちらを使用するかは、使用している RDBMS と特定のバージョン (たとえば、INサブクエリは非効率的な実行計画を作成する可能性があるため、ほとんどのバージョンの MySQL では避ける必要があります)、特定のテーブル サイズ、分散、インデックスなどによって異なります。

私は通常、EXISTS解決策を好みますが、最初に、現在使用している、または将来使用する予定のテーブル サイズでさまざまなクエリをテストし、ケースに最適なクエリとインデックスの組み合わせを見つけようとすることは決して悪いことではありません。


追加: 組み合わせに一意の制約がある場合、film_rating_report (filmid, rating)つまり映画が 2 つの同じ評価を得ることはないことを意味する場合、またはより厳密な (しかしより妥当な) 一意の制約がある場合film_rating_report (filmid)は、すべての映画の評価が最大で 1 つであることを意味します。ソリューションを簡素化できますJOIN(そして、他のすべてのクエリを取り除くことができます):

    SELECT f.*
    FROM film AS f
        JOIN film_rating_report AS frr
             ON f.filmid = frr.filmid
    WHERE frr.rating = 'GE' ;
于 2013-07-01T10:32:07.610 に答える
3

これに対する推奨される解決策は、を使用することです。行が重複しないようにjoin忘れないでください。group by

select film.*
from film
join film_rating_report on film.filmid = film_rating_report.filmid
        and rating = 'GE'
group by film.filmid

編集: @ypercube によって正しく指摘されているように、私は、結合とグループ化のパフォーマンスがexistsorでサブクエリを使用するよりも優れていると主張するのは間違っていましたin- まったく逆です。

于 2013-07-01T08:17:02.373 に答える
1

クエリ:

SELECT t1.* 
FROM film t1 
WHERE EXISTS (SELECT filmid 
              FROM film_rating_report t2
              WHERE t2.rating = 'GE'
              AND t2.filmid = t1.id);
于 2013-07-01T08:17:42.523 に答える
-1

DB構造を知らなくても(テーブルにSHOW CREATE TABLEを与えることを検討してください)、これはうまくいくと思いますが、確実に知る方法はありません:

SELECT film.*
FROM (film)
LEFT JOIN film_rating_report ON film.filmid = film_rating_report.filmid AND film_rating_report.rating = 'GE'
WHERE film_rating_report.filmid IS NOT NULL
GROUP BY film.filmid

( WHERE film_rating_report.filmid IS NOT NULLは、求めている評価がない行が忍び寄るのを防ぎます。最後にGROUP BYを追加しました。これは、 film_rating_reportが複数回一致する可能性があるためです。保存されているデータを確認できるのでわかりません初期化)

于 2013-07-01T08:13:03.900 に答える