Oracle 中的平均查询

Posted

技术标签:

【中文标题】Oracle 中的平均查询【英文标题】:Average query in Oracle 【发布时间】:2013-12-03 21:22:49 【问题描述】:

我有一个包含这四个表的数据库:

CREATE TABLE team (  
      id    CHAR(3),  
      name     VARCHAR2(80) CONSTRAINT nn_team_name     NOT NULL,  
      district VARCHAR2(20) CONSTRAINT nn_team_district NOT NULL,  

CONSTRAINT pk_team  
PRIMARY KEY (id)  
);  

 CREATE TABLE game (  
     home,        
     away,  
     round    NUMBER(2) CONSTRAINT nn_game_round NOT NULL,  
     spectators NUMBER(5),  
--  
 CONSTRAINT pk_game  
      PRIMARY KEY (home, away),  
--  
 CONSTRAINT fk_game_home  
      FOREIGN KEY (home)  
      REFERENCES team(id),  
 CONSTRAINT fk_game_away  
      FOREIGN KEY (away)  
      REFERENCES team(id),  
--
 CONSTRAINT ck_game_round  
     CHECK (round BETWEEN 1 AND 30),  
 CONSTRAINT ck_game_spectators
    CHECK (spectators > 0)
);

CREATE TABLE player (  
     nickname        NUMBER(8),  
     name       VARCHAR2(80) CONSTRAINT nn_player_name      NOT NULL,  
     yearOfBirth NUMBER(4)    CONSTRAINT nn_player_yearOfBirth NOT NULL,   
     team                  CONSTRAINT nn_player_team    NOT NULL,  
--
CONSTRAINT pk_player  
    PRIMARY KEY (nickname),  
--
CONSTRAINT fk_player_team  
    FOREIGN KEY (team)  
    REFERENCES team(id),  
--
CONSTRAINT ck_player_yearOfBirth  
    CHECK (yearOfBirth BETWEEN 1950 AND 2000)  
);

CREATE TABLE plays (  
    player,  
    home,         
    away,    
    goals      NUMBER(2) CONSTRAINT nn_plays_goals NOT NULL,  
--
CONSTRAINT pk_plays  
    PRIMARY KEY (player, home, away),  
--
CONSTRAINT fk_plays_player  
     FOREIGN KEY (player) REFERENCES player(nickname),  
CONSTRAINT fk_plays_game  
     FOREIGN KEY (home, away) REFERENCES game(home, away),  
--
CONSTRAINT ck_plays_goals   
     CHECK (goals >= 0)  

);

我在处理这四个查询时遇到了问题:

每场比赛每轮的平均进球数。结果应按整数排序。 在不到五场比赛中客场比赛的球员的姓名和昵称,以及他们的球队 ID。结果应该包括没有参加任何比赛的球员。必须只有一个 SELECT 子句。 每轮进球数较多的球队的 ID。如果有不止一支球队的进球数较多,则两支球队都应显示在结果中。假设球队在每一轮比赛。 他们俱乐部的昵称和身份证,用于在两场比赛中进球最多的球员,并且只有两场比赛。如果在这种情况下有多个玩家,则不会显示任何人。

你们能帮帮我吗?因为我已经设法进行了更简单的查询,但我被困在了这个...

【问题讨论】:

SQL*PLUS 是 oracle 的东西,而不是 mysql 的东西。 @OllieJones 抱歉,我已经更新了! 你有测试数据吗?可以发SQLFIDDLE吗? 【参考方案1】:

未测试,因为我没有任何测试数据...

查询 1

--    Average number of goals per game per round.
--    The result should be ordered by round number.
WITH num_games AS (
  SELECT COUNT(1) AS num_games,
         round
  FROM   game
  GROUP BY round
)
SELECT g.round,
       SUM( p.goals / n.num_games )
         AS avg_goals_per_game_per_round
FROM   game g
       INNER JOIN
       plays p
       ON ( g.home = p.home AND g.away = p.away )
       INNER JOIN
       num_games n
       ON ( g.round = n.round )
GROUP BY g.round
ORDER BY g.round;

查询 2

--    Names and nicknames of the players, and their team id's,
--    that played away in less than five games.
--    The result should include the players that didn't played in any game.
--    There must be ONLY one SELECT clause.
SELECT p.nickname,
       p.name,
       p.team
FROM   player p
       LEFT OUTER JOIN
       plays l
       ON ( p.nickname = l.player )
GROUP BY p.nickname, p.name, p.team
HAVING COUNT( 1 ) < 5;

查询 3

--    id's of the teams with the larger number of goals against per round.
--    In case there's more than one team with the larger number
--    of goals against, both teams should show in the result.
--    Assume the teams play in every round.
WITH player_home_or_away_goals AS (
  SELECT player,
         home,
         away,
         goals,
         CASE WHEN home = (SELECT team
                           FROM   player p
                           WHERE  p.nickname = l.player)
              THEN 'H'
              ELSE 'A'
              END AS home_away
  FROM   plays l
),
game_home_or_away_goals AS (
  SELECT home,
         away,
         SUM( DECODE( home_away, 'H', goals, null ) ) AS home_goals,
         SUM( DECODE( home_away, 'A', goals, null ) ) AS away_goals
  FROM   player_home_or_away_goals
  GROUP BY home, away
),
team_goals_per_game_per_round AS (
  SELECT g.home AS team_id,
         h.home_goals AS goals_for,
         h.away_goals AS goals_against,
         g.round
  FROM   game g
         INNER JOIN
         game_home_or_away_goals h
         ON ( g.home = h.home AND g.away = h.away )
  UNION ALL
  SELECT g.away AS team_id,
         h.away_goals AS goals_for,
         h.home_goals AS goals_against,
         g.round
  FROM   game g
         INNER JOIN
         game_home_or_away_goals h
         ON ( g.home = h.home AND g.away = h.away )
),
total_team_goals_per_round AS (
  SELECT team_id,
         round,
         SUM( goals_for )     AS total_goals_for_per_round,
         SUM( goals_against ) AS total_goals_against_per_round
  FROM   team_goals_per_game_per_round
  GROUP BY team_id,
           round
),
max_goals_against_per_round AS (
  SELECT round,
         MAX( total_goals_against_per_round ) AS greatest_goals_against
  FROM   total_team_goals_per_round
  GROUP BY round
)
SELECT t.team_id,
       t.round
FROM   total_team_goals_per_round t
       INNER JOIN
       max_goals_against_per_round m
       ON (    t.round = m.round
           AND t.total_goals_against_per_round = m.greatest_goals_against );

查询 4

--    Nicknames and id's of their clubs, for the players that scored
--    the larger number of goals in two, and only two games. If there
--    are more than one player in this conditions, none is shown.

请发布一些测试数据和所需的输出,因为不清楚这个问题的确切要求是什么。

您想要只玩两场比赛的玩家子集,然后从该子集中找到得分最高的玩家吗? 或者,您是否想要在两场比赛中得分最高的球员,而不管他们总共打了多少场比赛? 或者,是别的什么吗?

【讨论】:

在什么方面令人困惑或不简单?查询 2 尽可能简单。查询 1 可能有另一种解决方案,但我无法立即想到它。 我如何发送一些测试数据? 我想要在两场比赛中得分最高的球员,无论他们总共打了多少场比赛 你的第三个查询看起来真的很混乱,你能试着让更简单一点吗?或者解释一下发生了什么?

以上是关于Oracle 中的平均查询的主要内容,如果未能解决你的问题,请参考以下文章

用oracle怎样查询每个部门的部门编号,部门名称,平均工资,最高工资和最低工资

Oracle 多表查询

oracle 分组查询 子查询 统计查询 FROM加子查询临时表 查询高于平均工资 示例代码

Oracle - 如何从子查询中返回平均值?

oracle的SQL语句中,查询每个学生的的学号、姓名、平均成绩,结果按平均成绩降序排列。

Oracle SQL 查询移动平均线