所以我在一个幻想电影联盟(比如足球,但不是球员,你选择电影),我为它运行网站。我基本上试图用MySQL和PHP做的是:在主页上列出当前年份(1)中的每部电影,并让它显示每部电影的总分。每部电影的总分都基于以下公式:
metacritic + (imdb*10) + top_bottom + power(receipts,(2/9)) + ALL OTHER AWARDS POINTS
我的问题是,所有的奖励积分都在第二张表中,两张真的。一张桌子被称为“奖励”,其中包含所有奖项和点数值,第二张表格“awards_won”记录了每部电影赢得或被提名的所有奖项。
我相信我想要做的是根据“awards_won.film_nominated”和/或“awards_won.film_won”= 1来使用子查询计算每部电影的奖励积分。
这段代码非常符合我的要求:
SELECT title,
( select sum(awards.nom_points)
from awards_won
left join awards on awards.id = awards_won.award_id
where movie_id = 25 and awards_won.film_nominated = 1
) as total_nom_points,
( select sum(awards.win_points)
from awards_won
left join awards on awards.id = awards_won.award_id
where movie_id = 25 and awards_won.film_won = 1
) as total_win_points,
( select total_win_points + total_nom_points) as total_award_points
FROM movies
LEFT JOIN awards_won on awards_won.movie_id = movies.id
WHERE movie_id = 25 and movies.year_id = 1;
除非我想为每部电影做一遍,否则我不能在循环中使用“where movie_id = 25”...所以这就是我被困住的地方。希望这是有道理的。
以下是表格说明:
CREATE TABLE `movies` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`year_id` int(2) NOT NULL,
`title` varchar(100) NOT NULL,
`release_date` date DEFAULT NULL,
`metacritic` int(3) NOT NULL,
`imdb` decimal(2,1) NOT NULL,
`top_bottom` int(3) NOT NULL,
`receipts` int(10) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `awards` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`festival_id` int(2) NOT NULL,
`award_title` varchar(100) NOT NULL,
`nom_points` int(2) NOT NULL,
`win_points` int(2) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `award_title_and_festival` (`award_title`,`festival_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `awards_won` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`award_id` int(2) NOT NULL,
`movie_id` int(2) NOT NULL,
`nominee_name` varchar(100) NOT NULL,
`film_nominated` tinyint(1) NOT NULL,
`film_won` tinyint(1) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `year_award_title_id` (`award_id`,`movie_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
PS:我理解如何在PHP中使用foreach循环显示数组变量,因此SQL语句是我的主要问题。提前谢谢!
示例数据:
INSERT INTO `movies` (id, year_id, title, release_date, metacritic, imdb, top_bottom, receipts)
VALUES (1,1,'All Is Lost','2013-10-18',87,7.4,7,5947690);
INSERT INTO awards (id, festival_id, award_title, nom_points, win_points)
VALUES (1,3,'Best Picture',4,16), (2,3,'Best Lead Actor',4,16), (3,3,'Best Score',2,8);
INSERT INTO awards_won (id, award_id, movie_id, nominee_name, film_nominated, film_won)
VALUES (1,1,1,'All Is Lost',1,0), (2,2,1,'Robert Redford',1,1), (3,3,2,'Hans Zimmer',1,0);
这适用于一部电影,我只需要一个循环
SELECT title,
( select sum(awards.nom_points)
from awards_won
left join awards on awards.id = awards_won.award_id
where movie_id = 1
and awards_won.film_nominated = 1
) as total_nom_points,
( select sum(awards.win_points)
from awards_won
left join awards on awards.id = awards_won.award_id
where movie_id = 1
and awards_won.film_won = 1
) as total_win_points,
( select IFNULL(total_win_points,0) + IFNULL(total_nom_points,0)
) as total_award_points
FROM movies
LEFT JOIN awards_won on awards_won.movie_id = movies.id
WHERE movie_id = 1
and movies.year_id = 1;
这将为电影1提供8个total_nom_points,16个total_win_points和24个total_award_points
答案 0 :(得分:0)
尝试此查询:
SELECT m.id,
m.title,
sum(if(aw.film_nominated = 1,a.nom_points,0)) AS total_nom_points,
sum(if(aw.film_won = 1,a.win_points,0)) AS total_win_points,
sum(if(aw.film_nominated = 1,a.nom_points,0))
+
sum(if(aw.film_won = 1,a.win_points,0)) AS TOTAL_AWARD_POINTS
FROM awards_won aw
JOIN movies m ON m.id = aw.movie_id
LEFT JOIN awards a ON a.id = aw.award_id
WHERE 1 IN (aw.film_nominated,aw.film_won)
AND m.year_id = 1
GROUP BY m.id
;
演示:http://www.sqlfiddle.com/#!2/d804d9/7
使用外部联接显示所有电影,即使它们在awards
表中没有任何记录
这是使用RIGHT JOIN
:
SELECT m.id,
m.title,
sum(if(aw.film_nominated = 1,a.nom_points,0)) AS total_nom_points,
sum(if(aw.film_won = 1,a.win_points,0)) AS total_win_points,
sum(if(aw.film_nominated = 1,a.nom_points,0))
+
sum(if(aw.film_won = 1,a.win_points,0))
AS TOTAL_AWARD_POINTS
FROM awards_won aw
RIGHT JOIN movies m ON m.id = aw.movie_id
LEFT JOIN awards a ON a.id = aw.award_id
WHERE ( 1 IN (aw.film_nominated,aw.film_won)
OR aw.id IS NULL
)
AND m.year_id = 1
GROUP BY m.id
;
并使用LEFT JOIN
(表的顺序在这里不同):
SELECT m.id,
m.title,
sum(if(aw.film_nominated = 1,a.nom_points,0)) AS total_nom_points,
sum(if(aw.film_won = 1,a.win_points,0)) AS total_win_points,
sum(if(aw.film_nominated = 1,a.nom_points,0))
+
sum(if(aw.film_won = 1,a.win_points,0))
AS TOTAL_AWARD_POINTS
FROM movies m
LEFT JOIN awards_won aw ON m.id = aw.movie_id
LEFT JOIN awards a ON a.id = aw.award_id
WHERE ( 1 IN (aw.film_nominated,aw.film_won)
OR aw.id IS NULL
)
AND m.year_id = 1
GROUP BY m.id
;
演示:http://www.sqlfiddle.com/#!2/4d108/6
请注意这两个查询中的附加条件,如果没有它们,它们将无法正常工作:
WHERE ( 1 IN (aw.film_nominated,aw.film_won)
OR aw.id IS NULL
)
答案 1 :(得分:0)
试试这个:
SELECT title, IFNULL(nom_points.`value`,0) as total_nom_points,
IFNULL(win_points.`value`,0) as total_win_points,
(IFNULL(nom_points.`value`,0) + IFNULL(win_points.`value`,0)) as total_award_points
FROM movies
LEFT JOIN ( SELECT movie_id, sum(awards.nom_points) as `value`
FROM awards_won
LEFT JOIN awards on awards.id = awards_won.award_id
WHERE awards_won.film_nominated = 1
GROUP BY movie_id
) as nom_points on nom_points.movie_id = movies.id
LEFT JOIN ( select movie_id, sum(awards.win_points) AS `value`
FROM awards_won
LEFT JOIN awards on awards.id = awards_won.award_id
WHERE awards_won.film_won = 1
GROUP BY movie_id
) as win_points on win_points.movie_id = movies.id
WHERE movies.year_id = 1;
检查此fiddle