【问题标题】:Computed Column as Average from Other Data in Another Table计算列作为另一个表中其他数据的平均值
【发布时间】:2018-09-07 19:19:02
【问题描述】:

我正在创建一个简单的电影网站,允许用户浏览电影标题,并使用 5 分评分系统对电影进行评分。我正在使用 XAMPP 和 phpAdmin 通过 SQL 语言存储我的数据库。我有下表存储评级:

CREATE TABLE `movie_ratings` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `movie_id` int(11) DEFAULT NULL,
  `rating` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1;

我有下表存储电影:

CREATE TABLE `movies` (
  `movie_title` varchar(255) NOT NULL,
  `movie_id` int(100) NOT NULL,
  `genre` text NOT NULL,
  `release_date` text NOT NULL,
  `price` int(100) NOT NULL,
  `year` year(4) NOT NULL,
  `description` text NOT NULL,
  `movie_image` text NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

我想在我的电影表中添加一列average_rating,它基本上从特定movie_id 的movie_ratings 中获取所有评分值并对它们进行平均,然后将值存储到电影表中这个新的average_rating 列中。

我相信我需要一个计算列,但我只知道如何通过同一个表中的列来执行此操作,这里我使用的是另一个表。我读到也可以查看视图...尽管将电影的平均评分存储为新列。

所以我创建了一个视图,但它只显示一部电影并取平均值。

CREATE VIEW movie_ratings_view AS 
    SELECT b.movie_id, b.movie_title, b.movie_image, b.price, AVG(br.rating) 
    AS avgRating FROM movies b INNER JOIN movie_ratings br ON 
    b.movie_id = br.movie_id;

【问题讨论】:

  • 这是什么数据库? “SQL”作为标签并不能告诉我们足够的信息。似乎是MySQL。您是否考虑过使用包含所需计算的“视图”(因此不尝试存储它)?
  • @Used_By_Already 是的,这是 MySQL,我已经添加了标签。是的,我考虑过创建一个视图,但我想我也可以存储它。但是经过研究,似乎只有一个函数可以做到这一点。所以一个视图毕竟会更合适......我现在会尝试创建一个视图,看看它是否最终工作并更新问题。
  • @Used_By_Already 现在再次查看我的问题并添加了一个视图,你能告诉我它有什么问题吗?
  • 请注意,我添加了一个替代查询以供考虑。
  • 谢谢您,最初的回答效果很好!

标签: mysql sql


【解决方案1】:

对于视图最有效的代码可能是相关子查询:

CREATE VIEW movie_ratings_view AS
    SELECT m.movie_id, m.movie_title, m.movie_image, m.price
           (SELECT AVG(mr.rating)
            FROM movie_ratings mr
            WHERE mr.movie_id = m.movie_id
           ) as avgRating
    FROM movies m;

这可以利用movie_ratings(movie_id, rating) 上的索引。而且它没有可能很昂贵的外部GROUP BY

略有不同,因为这将返回没有评分的电影——但这甚至可能是可取的。

【讨论】:

    【解决方案2】:

    你需要一个group by 子句

    CREATE VIEW movie_ratings_view
    AS
    SELECT
          b.movie_id
        , b.movie_title
        , b.movie_image
        , b.price
        , AVG(br.rating) AS avgRating
    FROM movies b
    INNER JOIN movie_ratings br ON b.movie_id = br.movie_id
    GROUP BY
          b.movie_id
        , b.movie_title
        , b.movie_image
        , b.price
    ;
    

    另一种选择(如果/当 MySQL 在视图的 from 子句中允许子查询时):

    CREATE VIEW movie_ratings_view
    AS
    SELECT
          m.movie_id
        , m.movie_title
        , m.movie_image
        , m.price
        , COALESCE(mr.numRatings, 0) AS numRatings
        , COALESCE(mr.avgRating, 0)  AS avgRating
    FROM movies m
    LEFT JOIN (
          SELECT
                movie_id
              , COUNT(rating) AS numRatings
              , AVG(rating)   AS avgRating
          FROM movie_ratings
          GROUP BY movie_id) mr ON m.movie_id = mr.movie_id
    ;
    

    【讨论】:

    • @GordonLinoff 是的......谢谢......添加了一个注释......一个非常烦人的限制
    猜你喜欢
    • 1970-01-01
    • 2014-11-04
    • 1970-01-01
    • 2018-11-03
    • 1970-01-01
    • 1970-01-01
    • 2018-09-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多