使用从另一个表MYSQL获取的值从一个表中选择行

时间:2013-07-01 08:04:21

标签: mysql

我目前在db

中有2个mysql表

FilmFilm_Ratings_Report

电影的主键是filmid,用于识别Film_Ratings_Report表中的电影评级。

我想知道是否可以使用MYSQL查询来搜索评级表并收集符合特定条件的所有电影ID,然后使用所选的ID从电影表中获取电影标题。下面是我使用的MYSQL查询:

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

我对MYSQL比较环保,对此有任何帮助。

先谢谢

5 个答案:

答案 0 :(得分:16)

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

应该有效

答案 1 :(得分:13)

您似乎想要 semi-join ,例如一个连接,只需要来自2个连接表之一的数据。在这种情况下,film中的所有行都在film_rating_report中有匹配的行,其中包含所需条件(rating = 'GE')。

这并不完全等同于通常的连接,因为即使第二个表中有2行(或更多)(电影的2个等级,都有'GE'),我们仍然希望电影是显示一次,而不是两次(或多次)显示通常的连接。

有多种方式可以编写半连接,最常用的是:

  • 使用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's answer):
    (如果连接列(在这种情况下为两个filmid)可以为空,那么它应该非常谨慎地使用,因为它可能会返回意外结果 - 或者根本不会 - 但

    SELECT * 
    FROM film 
    WHERE id IN 
      ( SELECT filmid 
        FROM film_rating_report 
        WHERE rating = 'GE'
      );
    
  • 使用通常的JOINGROUP BY来避免结果中的重复行(@Tomas' answer):
    (并注意GROUP BY的这种特定用途仅适用于MySQL和Postgres的最新版本,如果您想在其他DBMS中编写类似的查询,则必须包含所有列:{{1} })

    GROUP BY f.filmid, f.title, f.director, ...
  • @ Tomas'es答案的变体,其中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 ; 在派生表上完成,然后是GROUP BY

    JOIN

使用哪一个取决于RDBMS和您使用的特定版本(例如,在大多数MySQL版本中应避免使用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 ; 子查询,因为它们可能会产生低效的执行计划),您的特定表大小,分配,索引等。

我通常更喜欢IN解决方案,但是首先使用您将来或期望拥有的表大小来测试各种查询并尝试为您的案例找到最佳查询索引组合永远不会受到伤害。


另外:如果EXISTS组合存在唯一约束,这意味着没有电影可以获得两个相同的评级,或者{{1}是否存在更严格(但更合理)的唯一约束这意味着每部电影最多只有一个评级,你可以简化film_rating_report (filmid, rating)解决方案(并摆脱所有其他查询):

film_rating_report (filmid)

答案 2 :(得分: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正确指出的那样,我错误地宣称加入& amp; group by比使用existsin的子查询更好 - 恰恰相反。

答案 3 :(得分:1)

查询:

SELECT t1.* 
FROM film t1 
WHERE EXISTS (SELECT filmid 
              FROM film_rating_report t2
              WHERE t2.rating = 'GE'
              AND t2.filmid = t1.id);

答案 4 :(得分:-1)

我相信这会有效,想到不知道你的数据库结构(考虑在你的表上给出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 可能会多次匹配 - 不确定,因为我可以看到存储在其中的数据)