MySQL获取所有出现超过平均外观的行

时间:2018-11-06 18:19:23

标签: mysql sql

我有一个演员表,其中每个演员出现在不同的电影中,我尝试只选择出现次数超过每个演员平均出现次数的演员。

这是我的尝试,但结果会产生相同的名称,但外观值不同,因此我认为我有误

 SELECT 
   a.first_name AS fname, 
   a.last_name AS lname, 
   films_per_actor.num_films 
 FROM 
   actor as a, 
   (
     SELECT 
       AVG(num_films) AS avg_films_num 
     FROM 
       (
         SELECT 
           COUNT(film_id) AS num_films, 
           a.actor_id 
         FROM 
           film_actor as f_a, 
           actor as a 
         WHERE 
           f_a.actor_id = a.actor_id 
         GROUP BY 
           actor_id
       ) as films_per_actor1
   ) as avg_films, 
   (
     SELECT 
       COUNT(film_id) AS num_films, 
       a.actor_id 
     FROM 
       film_actor as f_a, 
       actor as a 
     WHERE 
       f_a.actor_id = a.actor_id 
     GROUP BY 
       actor_id
   ) as films_per_actor 
 WHERE 
   films_per_actor.num_films > avg_films.avg_films_num + 10 
 ORDER BY 
   fname, 
   lname

但结果是

"ADAM"  "GRANT" "40"
"ADAM"  "GRANT" "39"
"ADAM"  "GRANT" "42"
"ADAM"  "GRANT" "41"
"ADAM"  "HOPPER"    "40"
"ADAM"  "HOPPER"    "39"
"ADAM"  "HOPPER"    "42"
"ADAM"  "HOPPER"    "41"
"AL"    "GARLAND"   "40"
"AL"    "GARLAND"   "39"
"AL"    "GARLAND"   "41"
"AL"    "GARLAND"   "42"
"ALAN"  "DREYFUSS"  "39"
"ALAN"  "DREYFUSS"  "40"
"ALAN"  "DREYFUSS"  "42"
"ALAN"  "DREYFUSS"  "41"

1 个答案:

答案 0 :(得分:0)

正如@Eric所说,使用现代的显式JOIN语法可能会完全避免此问题。 actor表和两个子查询之间没有连接条件。因此,您将获得每个演员,每个演员的人数都超过平均值。

此外,可以通过多种方式简化查询

SELECT 
  a.first_name AS fname, 
  a.last_name AS lname, 
  fpa.num_films 
FROM 
  actor as a 
  INNER JOIN (
    SELECT 
      actor_id, 
      COUNT(film_id) AS num_films 
    FROM 
      film_actor 
    GROUP BY 
      actor_id
  ) AS fpa ON a.actor_id = fpa.actor_id 
  INNER JOIN (
    SELECT 
      COUNT(*)/ COUNT(DISTINCT actor_id) AS avg_films_num 
    FROM 
      film_actor
  ) AS avg_films ON fpa.num_films > avg_films.avg_films_num 
ORDER BY 
  fname, 
  lname

或者:

  SELECT 
  a.first_name AS fname, 
  a.last_name AS lname, 
  fpa.num_films 
FROM 
  actor as a 
  INNER JOIN (
    SELECT 
      actor_id, 
      COUNT(film_id) AS num_films 
    FROM 
      film_actor 
    GROUP BY 
      actor_id
  ) AS fpa ON a.actor_id = fpa.actor_id 
WHERE 
  fpa.num_films > (
    SELECT 
      COUNT(*)/ COUNT(DISTINCT actor_id) AS avg_films_num 
    FROM 
      film_actor
  ) 
ORDER BY 
  fname, 
  lname