3

データベースの先生から、(Oracle サーバーで) クエリを書くように言われました: 2010 年の平均スコアが最も高いグループ ID を選択してください

私が書いた:

SELECT * FROM (
    SELECT groupid, AVG(score) average FROM points
    WHERE yr = 2010
    AND score IS NOT NULL
    GROUP BY groupid
    ORDER BY average DESC
) WHERE rownum = 1;

私の先生は、この要求が「より良い」と私に言いました:

SELECT groupid, AVG(score) average FROM points
WHERE yr = 2010
GROUP BY groupid
HAVING AVG(score) >= ALL (
    SELECT AVG(score) FROM points
    WHERE yr = 2010
    GROUP BY groupid
);

どれが最速/より良いですか? より良い解決策もありますか (Oracle のみ) ? ありがとう。

4

3 に答える 3

3

先生がおっしゃる理由は2つあります。

  1. データ・モデル。リレーショナル DBMS は、リストではなくセットを扱います。SQL を学習している場合は、順序付きリストよりも、順序付けされていないタプルのセットについて考える方が適切です。DBMS のクエリ方法をよりよく理解できるようになります。私はあなたの解決策をハックだと考えています.Perun_xが指摘したように、部分的に機能するものは---複数のタプルが結果に一致する場合は機能しません。これは SQL のデータ モデルと精神に反します)。

  2. 携帯性。これが本当の殺人者です。コードは Oracle では機能しますが、row_number 属性をサポートしていない他の DBMS では機能しません (それぞれ独自の方法があります)。

--dmg

于 2013-04-28T17:42:53.940 に答える
2

必要なものには1行で十分であると仮定して、たまたまあなたのバージョンを好みます。教師用バージョンの私の問題は、主に読みやすさです。解析するのは難しいと思います。

あなたのバージョンは本質的に「グループを平均で並べ替え、平均が最も高いグループを採用する」と言っています。教師版は基本的に、「グループの平均のいずれか以上の平均を見つけてください」と言っています。これは主観的かもしれませんが、後者よりも前者の方が理解しやすいと思います。

どちらが速いかというと。最良の値を得るには、集計と並べ替えを行う必要があります。2 番目のバージョンでは、2 つの集計と結合を行う必要があります。集約/ソート方法の方が高速だと思いますが、実際に知る唯一の方法は、特定のシステム構成とデータ セットのパフォーマンスをチェックすることです。

パフォーマンスの点であなたのものとほぼ同等であるはずの別の定式化は次のとおりです。

select groupid, avgscore
from (select groupid, avg(score) as avgscore,
             row_number() over (order by avg(score) desc) as seqnum
     from points
     where yr = 2010
     group by groupid
    ) t
where seqnum = 1

ここでの利点は、 を変更しrow_number()dense_rank()、最適な行の 1 つまたはすべての行を取得できることです。

于 2013-04-28T17:11:51.643 に答える
2

クエリは同等ではありません。最初のクエリは常に 1 行を選択します。2 番目の行は、平均が最も高いすべての行を選択します (理論的には、そのような行がさらに存在する可能性があります)。

于 2013-04-28T16:34:14.967 に答える