如何在MySQL LEFT JOIN中使用别名

37

我的原始查询是使用WHERE子句进行连接,而不是使用JOIN。 我意识到这样做不能返回没有任何明星或流派的电影,所以我认为必须使用LEFT JOIN才能显示每个电影。 这是我的原始SQL:

SELECT *
FROM movies m, stars s, stars_in_movies sm, genres g, genres_in_movies gm
WHERE m.id = sm.movie_id
AND sm.star_id = s.id
AND gm.genre_id = g.id
AND gm.movie_id = m.id
AND m.title LIKE '%the%'
AND s.first_name LIKE '%Ben%'
ORDER BY m.title ASC
LIMIT 5;

我尝试进行左连接,但是肯定做错了什么。

SELECT *
FROM movies m, stars s, stars_in_movies sm, genres g, genres_in_movies gm
LEFT JOIN movies m1 ON m1.id = sm.movie_id
LEFT JOIN movies m2 ON m2.id = gm.movie_id
AND sm.star_id = s.id
AND gm.genre_id = g.id
ORDER BY m.title ASC
LIMIT 5;

我得到了 ERROR 1054 (42S22): Unknown column 'sm.movie_id' in 'on clause',很明显我的连接有问题,但我不知道是哪里出错了。


1
混合使用懒惰的 FROM table,table,table 和正确的完全指定连接是极其丑陋的。 - Marc B
混合使用隐式和显式JOINs - philipxy
5个回答

26
不要混淆逗号运算符和JOIN——它们具有不同的优先级!甚至在手册中都有关于这个问题的警告:

然而,逗号运算符的优先级低于INNER JOIN、CROSS JOIN、LEFT JOIN等。如果你将逗号连接与其他类型的连接混合使用,并且存在连接条件,可能会出现形如Unknown column 'col_name' in 'on clause' 的错误。本节稍后将介绍如何解决这个问题。

请尝试使用以下方法代替:

SELECT *
FROM movies m
LEFT JOIN (
   stars s
   JOIN stars_in_movies sm
       ON sm.star_id = s.id
) ON m.id = sm.movie_id AND s.first_name LIKE '%Ben%'
LEFT JOIN (
    genres g
    JOIN genres_in_movies gm
        ON gm.genre_id = g.id
) ON gm.movie_id = m.id
WHERE m.title LIKE '%the%'
ORDER BY m.title ASC
LIMIT 5;

我觉得这一行代码 AND m.title LIKE '%the%' 应该改为 WHERE m.title LIKE '%the%',对吗? - styfle
其他的AND应该改成WHERE吗?例如,如果我想要根据名字和姓氏进行查询:JOIN stars_in_movies sm ON sm.star_id = s.id WHERE s.first_name LIKE '%Ben%' AND s.last_name LIKE '%Stiller%' - styfle
1
@styfle:不,我甚至认为在那里写WHERE语句都是无效的SQL。 - Mark Byers
@styfle:我把那个条件移到了另一个地方,我现在觉得更合理。 - Mark Byers
两种方法对我来说仍然有点混淆,因为表别名在括号外使用。但我不能抱怨,因为这个方法有效! - styfle

7

你应该将与JOIN相关的条件放在同一个ON子句中。然而,对于你上述的问题,你应该使用以下查询:

SELECT *
FROM movies m 
LEFT JOIN stars_in_movies sm ON sm.movie_id = m.id
JOIN stars s ON sm.star_id = s.id
LEFT JOIN genres_in_movies gm ON gm.movie_id = m.id
JOIN genres g ON gm.genre_id = g.id
ORDER BY m.title ASC
LIMIT 5;

LEFT JOIN 返回 INNER JOIN 行 UNION ALL 扩展了 NULL 的未匹配左表行。始终知道 OUTER JOIN 的一部分是什么 INNER JOIN。在 LEFT JOIN 之后,需要右表列不为 NULL 的 WHERE、INNER JOIN 或 HAVING 将删除任何引入 NULL 的行,即仅保留 INNER JOIN 行,即“将 OUTER JOIN 转换为 INNER JOIN”。你已经有了这个。 (删除最后一个 LEFT 关键字不会改变任何结果。) - philipxy

1

有人警告这是一个黑客攻击。

SELECT *
FROM movies m, stars_in_movies sm
LEFT JOIN movies m1
ON m1.id = sm.movie_id
, stars s
ORDER BY m.title ASC
LIMIT 5;

与拥有你所比较的列的正确表格连接。


0

SQL Join(MySQL中的内连接)

select emp1.id,emp1.name,emp1.job  from (select id, type as name, description as job from component_type as emp1)emp1
inner join 
emp
on emp1.id=emp.id;

左连接

select emp1.id,emp1.name,emp1.job  from (select id, type as name, description as job from component_type as emp1 where id between '1' AND '5')emp1
left join 
emp
on emp1.id=emp.id;

右连接

select emp1.id,emp1.name,emp1.job  from (select id, type as name, description as job from component_type as emp1)emp1
Right join 
(select * from emp where id between '1' and '5')exe
on emp1.id=exe.id;

所有的示例都基于别名,有些表格可能有不同的列名,但数据属性是相等的。 - Rahul Panwar

-1

使用别名连接多个表而不使用join。

select sum(s.salary_amount) as total_expenses_paid_to_all_department
from salary_mas_tbl s,dept_mas_tbl d
where s.salary_dept=d.dept_id;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接