在循环中组合来自单独表的点

时间:2014-01-01 03:21:20

标签: php mysql

所以我在一个幻想电影联盟(比如足球,但不是球员,你选择电影),我为它运行网站。我基本上试图用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

2 个答案:

答案 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