具有多个左连接的SQL

时间:2015-07-15 22:11:42

标签: mysql sql selection

使用:http://dev.mysql.com/doc/sakila/en/

我试图写一个查询来计算每个演员按类别行事的电影数量。

非常感谢任何指示或建议。

到目前为止,这是我的代码(当我拿出第二个LEFT JOIN部分时,它正确计算了一个类别的影片):

SELECT actor.first_name, actor.last_name, 
COUNT(subset.film_id) AS action,
COUNT(subset2.film_id) AS animation
FROM actor
LEFT JOIN (
SELECT film.film_id, actor.actor_id 
FROM actor
INNER JOIN film_actor
ON film_actor.actor_id = actor.actor_id
INNER JOIN film 
ON film.film_id = film_actor.film_id
INNER JOIN film_category 
ON film_category.film_id = film.film_id
INNER JOIN category 
ON category.category_id = film_category.category_id
WHERE category.name = 'Action') AS subset 
ON subset.actor_id = actor.actor_id
LEFT JOIN (
SELECT film.film_id, actor.actor_id 
FROM actor
INNER JOIN film_actor
ON film_actor.actor_id = actor.actor_id
INNER JOIN film 
ON film.film_id = film_actor.film_id
INNER JOIN film_category 
ON film_category.film_id = film.film_id
INNER JOIN category 
ON category.category_id = film_category.category_id
WHERE category.name = 'Animation') AS subset2
ON subset2.actor_id = actor.actor_id
GROUP BY actor.actor_id
ORDER BY actor.last_name ASC;

3 个答案:

答案 0 :(得分:1)

如果您只想获得每个演员和类别的电影数量,那么您所获得的查询似乎非常复杂。

此查询:

SELECT 
    actor.first_name, actor.last_name, category.name, 
    COUNT(*) as CountPerCategory
FROM actor
JOIN film_actor ON film_actor.actor_id = actor.actor_id
JOIN film ON film.film_id = film_actor.film_id
JOIN film_category ON film_category.film_id = film.film_id
JOIN category ON category.category_id = film_category.category_id
GROUP BY actor.first_name, actor.last_name, category.name;

会给你一个输出:

Firstname, Lastname, Category, CountPerCategory
Clint      Eastwood  Animation 1
Clint      Eastwood  Action    15

但是如果你想要不同列中每个类别的计数,你可以利用MySQL为真实条件返回1的事实,并测试该类别是否匹配并使用sum(这也可能不包括案例表达式)一种更便携的方式),像这样:

SELECT 
    actor.first_name, actor.last_name, category.name
    , SUM(category.name = 'Animation') as CountOfAnimation
    , SUM(category.name = 'Action') as CountOfAction
FROM actor
JOIN film_actor ON film_actor.actor_id = actor.actor_id
JOIN film ON film.film_id = film_actor.film_id
JOIN film_category ON film_category.film_id = film.film_id
JOIN category ON category.category_id = film_category.category_id
GROUP BY actor.first_name, actor.last_name, category.name;

会产生如下结果:

Firstname, Lastname, CountOfAnimation, CountOfAction
Clint      Eastwood  1                 15

请注意,如果一部电影属于多个类别,则每个类别都会计算一次,这可能是您想要的(或不是)。

答案 1 :(得分:0)

这应该为您提供所有参与者的计数,包括与之关联的所有类别:

SELECT actor.first_name, actor.last_name, category.name
, COUNT(DISTINCT film.film_id)
FROM actor
LEFT JOIN film_actor ON film_actor.actor_id = actor.actor_id
LEFT JOIN film ON film.film_id = film_actor.film_id
LEFT JOIN film_category ON film_category.film_id = film.film_id
LEFT JOIN category ON category.category_id = film_category.category_id
GROUP BY actor.first_name, actor.last_name, category.name
;

如果您只想要特定的,请在GROUP BY行之后添加:

HAVING category.name IN ('Action', 'Animation')

如果您只想要拥有这些类别的演员,请将LEFT JOIN更改为INNER JOIN和/或将上述HAVING更改为WHERE(并相应地重新定位)。

答案 2 :(得分:0)

我同意,该查询看起来非常复杂,并且通过使用2个派生表,它也可能运行缓慢。此查询将在每个类别中提供唯一的电影,并且不会复制结果,因为没有多对多的连接。 它会在您添加类别时减慢,但是因为它必须多次扫描表格,但它会给出准确的结果,只要您的表格不是太大就应该没问题。

你可能不需要不同的,但如果出于某种原因,某人在电影上有两次相同的类别(或类似的东西),这将消除错误的空间。

select a.first_name, a.last_name
, (
select count(distinct f.id) 
from film f 
join film_actor fa on fa.film_id=f.film_id
join film_category fc on fc.film_id=f.film_id
join category c ON c.category_id = fc.category_id
where c.name='Animation'
and fa.actor_id=a.actor_id
) as unique_animation_films
, (
select count(distinct f.id) 
from film f 
join film_actor fa on fa.film_id=f.film_id
join film_category fc on fc.film_id=f.film_id
join category c ON c.category_id = fc.category_id
where c.name='Action'
and fa.actor_id=a.actor_id
) as unique_action_films
from actor a