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 分组查询 子查询 统计查询 FROM加子查询临时表 查询高于平均工资 示例代码