【问题标题】:How to match more than one rows using INNER JOIN with MySQL?如何使用 MySQL 的 INNER JOIN 匹配多行?
【发布时间】:2020-04-03 15:38:41
【问题描述】:

使用 INNER JOIN 选择标签为“动作”和“戏剧”的电影的正确方法是什么?

我试过这个查询,结果一定是“Taken, The Godfather”,但是没有返回结果。

SELECT 
    f.film_guid,
    f.film_name
FROM
    films as f
INNER JOIN
    film_labels as l ON l.film_guid = f.film_guid
WHERE
    l.label = 'Action' AND l.label = 'Drama'

表格:电影

+------------+----------------+
| film_guid  | film_name      |
+------------+----------------+
| filmguid_1 | Taken          |
| filmguid_2 | Matrix         |
| filmguid_3 | The Godfather  |
+------------+----------------+

表格:film_labels

+------------+----------------+
| film_guid  | label          |
+------------+----------------+
| filmguid_1 | Action         |
| filmguid_1 | Drama          |
| filmguid_1 | Family         |
| filmguid_2 | Action         |
| filmguid_3 | Action         |
| filmguid_3 | Drama          |
+------------+----------------+

【问题讨论】:

  • OR not AND..这是非常重要的事情
  • 我认为它不会起作用。这就是为什么我要问正确的方法来选择动作和戏剧。

标签: mysql sql join group-by


【解决方案1】:

您正在film_labels 中查找包含动作和戏剧的行,这不可能发生。您需要在与给定电影相对应的标签中搜索,这表明聚合:

SELECT f.film_guid, f.film_name
FROM films as f
INNER JOIN film_labels as l ON l.film_guid = f.film_guid
WHERE l.label IN ('Action', 'Drama')  -- either one, or the other
GROUP BY f.film_guid, f.film_name
HAVING COUNT(*) = 2                   -- both match

请注意,您也可以将exists 与相关子查询一起使用。键入的时间有点长,但 可能 更有效(使用正确的索引),因为它避免了聚合的需要:

SELECT f.*
FROM films as f
WHERE
    EXISTS (SELECT 1 FROM film_labels l WHERE l.film_guid = f.film_guid AND l.label = 'Action')
    AND EXISTS (SELECT 1 FROM film_labels l WHERE l.film_guid = f.film_guid AND l.label = 'Drama')

为了第二个查询的性能,您需要在film_labels(film_guid , label) 上建立索引。

【讨论】:

  • 如果需要更多标签,第一个示例更加灵活。例如,如果一部电影必须具有所有三个标签(动作、戏剧和家庭),您只需将“家庭”添加到 IN 子句并将计数更改为 3,如下所示:WHERE l.label IN ('Action', 'Drama', 'Family') GROUP BY f.film_guid, f.film_name HAVING COUNT(*) = 3。这在标签可变的情况下更有用。
  • 我曾经将标签存储在电影表中,如“动作、戏剧”组合,并使用 LIKE 查询进行搜索。如您所知,这不是搜索标签的有效方法。因此,我决定将标签移动到另一个表并使用 INNER JOIN 搜索它们。如果 @GMB 的方法比 LIKE 查询更快,我将更改我的查询。或者,您有更好的方法来存储和搜索标签吗?
  • 我会选择 GMB 的第一个解决方案。
  • 您在将标签存储在单独的表中的做法是正确的。
  • 我尝试了第一个具有 150 K+ 数据的解决方案,比 LIKE 查询慢得多。第一个解决方案需要 1.2 秒才能完成(使用索引。),LIKE 只需 0.2 秒。
猜你喜欢
  • 1970-01-01
  • 2011-05-29
  • 1970-01-01
  • 2014-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多