【问题标题】:How should I join these 3 SQL queries in Oracle?我应该如何在 Oracle 中加入这 3 个 SQL 查询?
【发布时间】:2011-01-03 15:28:24
【问题描述】:

我有这 3 个问题:

SELECT
  title, year, MovieGenres(m.mid) genres,
  MovieDirectors(m.mid) directors, MovieWriters(m.mid) writers,
  synopsis, poster_url
FROM movies m
WHERE m.mid = 1;

SELECT AVG(rating) FROM movie_ratings WHERE mid = 1;

SELECT COUNT(rating) FROM movie_ratings WHERE mid = 1;

我需要将它们加入到一个查询中。我能够这样做:

SELECT
  title, year, MovieGenres(m.mid) genres,
  MovieDirectors(m.mid) directors, MovieWriters(m.mid) writers,
  synopsis, poster_url, AVG(rating) average, COUNT(rating) count
FROM movies m INNER JOIN movie_ratings mr
  ON m.mid = mr.mid
WHERE m.mid = 1
GROUP BY
  title, year, MovieGenres(m.mid), MovieDirectors(m.mid),
  MovieWriters(m.mid), synopsis, poster_url;

但我不太喜欢那种“巨大”的 GROUP BY,有没有更简单的方法?

【问题讨论】:

  • 按照个人喜好编写“整洁”代码是愚蠢的。当你说,“我真的不喜欢那个‘巨大的’群体。”你听起来很不专业。我不是说这话是刻薄的。首先,从任何标准来看,它都不是很大。这是一个非常普通的小组。其次,它就是这样。您应该编写执行以下操作的查询; 1. 规模。数据库活动必须很好地扩展。 2. 可维护。您的查询应符合语法和格式标准。
  • 我强烈建议您消除 UDF。尽管它们可能会使 SQL 看起来更干净,但它们会破坏您的可伸缩性和性能。 Tom Kyte 的规则 1 是在 SQL 中做所有可以做的事情……当你不能在 SQL 中做时,在 PL/SQL 中做。如果director 和writer 只是其他关系表,则将它们全部连接起来。如果它们是 SOA 调用或类似的东西......然后离开它们。
  • 我的意思是这对我来说没有意义,必须有更好的方法。我的意思是,如果我必须选择一堆字段但不是全部(我可以使用 *),我必须将它们全部放在 GROUP BY 中,因为我只知道基础知识,这对我来说没有意义Oracle SQL,也许有更好的方法来做我所追求的,也许没有。这就是 SO 的用途,对吧?

标签: sql oracle join


【解决方案1】:

你可以这样做:

SELECT title
      ,year
      ,MovieGenres(m.mid) genres
      ,MovieDirectors(m.mid) directors
      ,MovieWriters(m.mid) writers
      ,synopsis
      ,poster_url
      ,(select avg(mr.rating) 
         from movie_ratings mr 
        where mr.mid = m.mid) as avg_rating
      ,(select count(rating)  
         from movie_ratings mr 
        where mr.mid = m.mid) as num_ratings
  FROM movies m
 WHERE m.mid = 1;

甚至

with grouped as(
   select avg(rating)   as avg_rating 
         ,count(rating) as num_ratings
     from movie_ratings 
    where mid = 1
)
select title
      ,year
      ,MovieGenres(m.mid) genres
      ,MovieDirectors(m.mid) directors
      ,MovieWriters(m.mid) writers
      ,synopsis
      ,poster_url
      ,avg_rating
      ,num_ratings
  from movies m cross join grouped
 where m.mid = 1;

【讨论】:

  • 哦,废了我的,我最喜欢那个。
  • 我从来不理解调用 3 个 SQL 查询或使用 3 个 SELECT 执行单个 SQL 查询之间的含义和区别...
  • @Nazgulled,你的意思是 3 个单独的数据库调用吗?
  • 当查询数量加起来时,它会影响可伸缩性。单独执行 10 毫秒的数据库调用可能看起来很快,但执行 1000 次则需要 10 秒。通常,最好“增加”并在更少的调用中执行更大的操作(只要它不会混淆优化器)。此外,对 PL/SQL 函数(MovieGenres、MovieDirectors、MovieWriters)的调用通常会导致基于行的处理,这对于像您这样的小型查询(我假设 mid 在您的示例中是唯一的?),但不能很好地扩展外部查询中的行数增加。
【解决方案2】:

我想我看不出有几个 GroupBy 列的问题。这是 SQL 中非常常见的模式。当然,代码的清晰性往往是旁观者的眼中钉。

检查这两种方法的解释计划;我猜你的原始版本会获得更好的性能,因为它只需要处理一次 movie_ratings 表。但我还没有检查过,这在一定程度上取决于数据和安装。

【讨论】:

    【解决方案3】:

    怎么样

    SELECT
      title, year, MovieGenres(m.mid) genres,
      MovieDirectors(m.mid) directors, MovieWriters(m.mid) writers,
      synopsis, poster_url,
      (SELECT AVG(rating) FROM movie_ratings WHERE mid = 1) av,
      (SELECT COUNT(rating) FROM movie_ratings WHERE mid = 1) cnt 
    FROM movies m
    WHERE m.mid = 1;
    

    SELECT
      title, year, MovieGenres(m.mid) genres,
      MovieDirectors(m.mid) directors, MovieWriters(m.mid) writers,
      synopsis, poster_url,
      av.av,
      cnt.cnt 
    FROM movies m,
      (SELECT AVG(rating) av FROM movie_ratings WHERE mid = 1) av,
      (SELECT COUNT(rating) cnt FROM movie_ratings WHERE mid = 1) cnt 
    WHERE m.mid = 1;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-13
      • 1970-01-01
      相关资源
      最近更新 更多