【问题标题】:Limiting a left join to returning one result?将左连接限制为返回一个结果?
【发布时间】:2012-07-08 11:04:27
【问题描述】:

我目前将此左连接作为查询的一部分:

LEFT JOIN movies t3 ON t1.movie_id = t3.movie_id AND t3.popularity = 0

麻烦的是,如果有几部电影同名同受欢迎(不要问,就是这样:-))然后返回重复的结果。

说了这么多,我想将左连接的结果限制为一个。

我试过了:

LEFT JOIN 
    (SELECT t3.movie_name FROM movies t3 WHERE t3.popularity = 0 LIMIT 1)
     ON t1.movie_id = t3.movie_id AND t3.popularity = 0

第二个查询因错误而终止:

Every derived table must have its own alias

我知道我要问的内容有些模糊,因为我没有提供完整的查询,但我要问的内容通常可能吗?

【问题讨论】:

  • 那是最后一个左连接,对吧?你不会去LEFT JOIN ... ON ... AND ... LEFT JOIN ... 是吗?声明末尾的LIMIT 1 不是您想要的吗?
  • 看看DISTINCTstatement,也许可以解决你的问题。
  • @jared - 它是查询中的最后一个LEFT JOIN,是的。前面还有两个。但是,我不能只在最后加上LIMIT 1,因为查询作为一个整体返回了很多行。
  • 这能回答你的问题吗? MySQL JOIN the most recent row only?

标签: php mysql join left-join


【解决方案1】:

错误很明显——您只需要在子查询结束 ) 之后为其创建一个别名,并在您的 ON 子句中使用它,因为每个表,无论是派生的还是真实的,都必须有自己的标识符。然后,您需要在子查询的选择列表中包含 movie_id 才能加入它。由于子查询已包含WHERE popularity = 0,因此您无需将其包含在连接的ON 子句中。

LEFT JOIN (
  SELECT
    movie_id, 
    movie_name 
  FROM movies 
  WHERE popularity = 0
  ORDER BY movie_name
  LIMIT 1
) the_alias ON t1.movie_id = the_alias.movie_id

如果您在外部 SELECT 中使用这些列之一,例如通过 the_alias.movie_name 引用它。

更好理解需求后更新:

要让每个组加入一个,您可以在 movie_id 上使用聚合 MAX()MIN() 并将其分组到子查询中。这样就不需要子查询 LIMIT - 您将收到每个名称的第一个 movie_id MIN() 或最后一个 MAX()

LEFT JOIN (
  SELECT
    movie_name,
    MIN(movie_id) AS movie_id
  FROM movies
  WHERE popularity = 0
  GROUP BY movie_name
) the_alias ON t1.movie_id = the_alias.movie_id

【讨论】:

  • 非常感谢您的帮助。我重写了查询以使其与您的示例一样,它几乎可以正常工作,但并不完全正常。如果我从语句中删除LIMIT 1,那么它会像以前一样返回多个结果(电影名称),但如果我在查询中留下LIMIT 1,则不会返回电影名称。知道为什么会这样吗?再次感谢。
  • @Nate 这有点奇怪。我输入了一个明确的ORDER BY(应该在那里),但我认为这不是原因。
  • @Nate 自己运行子查询并验证它是否返回正确的行以及您拥有的 WHERE 子句。
  • @Nate 你的 MySQL 版本是多少?旧版本不支持子查询中的LIMIT,尽管它至少从 5.0 开始工作。
  • 我知道发生了什么。它返回表中第一行的电影名称(在我的示例中),而不是当前电影。 IE。如果我在WHERE popularity = 0 之后添加AND movie_id = 2,那么它会返回该ID 的电影名称。我尝试添加AND movie_id = t1.movie_id,但由于错误Unknown column 't1.movie_id' in 'where clause' 而死。嗯..
【解决方案2】:
LEFT JOIN movies as m ON m.id = (
    SELECT id FROM movies mm WHERE mm.movie_id = t1.movie_id
    ORDER BY mm.id DESC
    LIMIT 1    
)

【讨论】:

    【解决方案3】:

    您可以尝试将GROUP BY t3.movie_id 添加到第一个查询中

    【讨论】:

      【解决方案4】:

      试试这个:

      LEFT JOIN 
          (
           SELECT t3.movie_name, t3.popularity   
           FROM movies t3 WHERE t3.popularity = 0 LIMIT 1
          ) XX
           ON  t1.movie_id = XX.movie_id AND XX.popularity = 0
      

      【讨论】:

        【解决方案5】:

        在 MySQL 5.7+ 上使用 ANY_VALUE & GROUP_BY:

        SELECT t1.id,t1.movie_name, ANY_VALUE(t3.popularity) popularity
        FROM t1
        LEFT JOIN t3 ON (t3.movie_id=t1.movie_id AND t3.popularity=0)
        GROUP BY t1.id
        

        更多信息 LEFT JOIN only first row

        https://dev.mysql.com/doc/refman/5.7/en/group-by-handling.html

        【讨论】:

          【解决方案6】:

          左加入最近/最近的 1 行的简单解决方案是使用选择而不是 ON 短语

          SELECT A.ID, A.Name, B.Content
          FROM A
          LEFT JOIN B
          ON A.id = (SELECT MAX(id) FROM B WHERE id = A.id)
          

          其中 A.id 是自增主键。

          【讨论】:

            猜你喜欢
            • 2014-01-27
            • 1970-01-01
            • 1970-01-01
            • 2021-03-15
            • 1970-01-01
            • 1970-01-01
            • 2013-01-23
            • 1970-01-01
            • 2021-09-21
            相关资源
            最近更新 更多