

以下のようなテーブル table1 があります。
*******************
table1
*******************
Name, Kyouka, Score, ID
*******************
山田, 国語, 92, 10001
鈴木, 国語, 71, 10002
田中, 国語, 89, 10003
山田, 数学, 65, 10004
鈴木, 数学, 69, 10005
杉田, 英語, 96, 10006
山田, 英語, 63, 10007
田中, 英語, 76, 10008
...
*******************
カラムIDはPRIMARYを指定しています。
カラムScoreはインデックスを作成しています。
このテーブルで、「IDと教科」を指定したときに、以下の2つのデータを得たいと思っています。
(1) IDに対応する名前と、その教科中の順位
(2) その教科のレコード数
具体例としては、例えば「ID=10001、教科=国語」を指定したときに、「山田、3人中1位」というような情報が得たいです。
(「ID=10001、教科=英語」のようなおかしな組み合わせは指定しないようになっています。)
(1) は、以下のようにして名前と順位を得る事が出来ました。
SELECT Name,
(SELECT COUNT(*) + 1 FROM table1 b WHERE b.Score > a.Score and Kyouka='国語') AS rank
FROM table1 a
WHERE ID='10001'
ORDER BY Score DESC;
(2)は、以下のようにして特定の教科のレコード数を得る事が出来ました。
SELECT COUNT(*) FROM table1 WHERE Kyouka='国語';
しかし、実際にはレコード数が大量にあり、頻繁にこの検索を実行する予定なので、負荷が心配です。
出来るだけサーバーの負荷を減らすために、1回のSELECT文の実行で(1)と(2)をどちらも実現できるような方法はないでしょうか。
また、このテーブルでインデックスを作成しているのはIDとScoreのみですが、より負荷を減らすにはKyoukaにもインデックスを作成した方が良いでしょうか。
何卒、よろしくお願いいたします。
No.3ベストアンサー
- 回答日時:
教科中の順位とその教科のレコード数を1回で取得するなら、下記の様にSELECT句内のサブクエリを一つ追加すれば良いだけです。
----------------------------------------
SELECT
Name,
Kyouka,
Score,
(SELECT COUNT(*) + 1 FROM table1 b WHERE b.Score > a.Score AND a.Kyouka = b.Kyouka) AS rank,
(SELECT COUNT(*) FROM table1 c WHERE a.Kyouka = c.Kyouka) AS count
FROM table1 a
WHERE ID = '10001'
ORDER BY Kyouka, Score DESC;
----------------------------------------
また、上記の様に教科をサブクエリ内の結合条件で絞り込んでやると、WHERE句の条件を変えるだけで色々な絞込みが可能です。
例) [国語の全データを取得] -------------
SELECT
Name,
Kyouka,
Score,
(SELECT COUNT(*) + 1 FROM table1 b WHERE b.Score > a.Score AND a.Kyouka = b.Kyouka) AS rank,
(SELECT COUNT(*) FROM table1 c WHERE a.Kyouka = c.Kyouka) AS count
FROM table1 a
WHERE Kyouka = '国語'
ORDER BY Kyouka, Score DESC;
----------------------------------------
性能が気になるようでしたら、下記の様にカウントはFROM句内のサブクエリで取得した方がよいかも知れません。
----------------------------------------
SELECT
Name,
Kyouka,
Score,
(SELECT COUNT(*) + 1 FROM table1 b WHERE b.Score > a.Score AND a.Kyouka = b.Kyouka) AS rank,
c.count
FROM table1 a INNER JOIN
(SELECT Kyouka, COUNT(*) AS count FROM table1 GROUP BY Kyouka) c USING(Kyouka)
ORDER BY Kyouka, Score DESC;
----------------------------------------
なお、他の方も指摘されている通り、Kyoukaカラムにもインデックスを張ったほうが良いと思います。
No.2
- 回答日時:
負荷を減らすという事なら、この場合SQLを1回にするよりも、
(2)の教科のレコード数は、ID別に毎回取得する必要は無さそうに思いますので、
その負荷が無駄になるという理由から、
(2)教科のレコード数は複数のIDに対して一回だけ取得し、
プログラムの変数等に格納しておくほうが効率的だと思います。
いずれにしてもKyoukaにインデックスを作成したほうがよいです。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# C言語 プログラミング 4 2022/05/22 11:53
- SQL Server [SQLServer] テーブル名からカラム名を取得する 1 2022/08/23 21:20
- MySQL 書籍の内容はまともでしょうか? 1 2023/01/22 03:07
- MySQL 三科目合計点のクラス別平均点求めるクエリ式を教えてください 1 2023/07/04 09:44
- MySQL 共通点はあります。何が違うのでしょうか? 1 2023/01/27 05:22
- MySQL 下記の問合せを行うクエリを、PhpMyAdminで作成して実行せよ。 第二回模試の3科目の各得点と合 1 2023/04/25 18:02
- Oracle sqlで質問です。 aテーブルとbテーブルがあり、下記のsqlで取得したidとnameに一致しないレ 1 2022/04/20 20:34
- Access(アクセス) アクセス 有効なフィールド名、または式として認識できませんのエラー 3 2022/08/19 11:53
- C言語・C++・C# C言語初心者 構造体 課題について 2 2023/03/10 19:48
- MySQL SQLです。こんな感じですか?あってますか? うまくいきません教えてくださいお願いします 1 2023/07/08 15:27
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
count集計の結果が0の場合でも...
-
SQLでフィールドの順番を変更し...
-
JOINで1つのテーブルに空白があ...
-
MySQLで複数のSELECT文を1文に...
-
差し込み後、元データを変更し...
-
for whichの使い方
-
エクセルの関数について教えて...
-
EXISTSを使ったDELETE文
-
エクセルで最後の文字だけ置き...
-
外部参照してるキーを主キーに...
-
SELECT 文 GROUP での1件目を...
-
フィルターかけた後、重複を除...
-
誰か教えてください
-
python random.choice について
-
テーブルの内容とテーブルのカ...
-
SQLServerで文字列の末尾からあ...
-
スクリーンセイバー
-
ストアド内で動的にSQLを作る際...
-
日付について
-
Outlook 送受信エラー
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
INSERT文でフィールドの1つだ...
-
count集計の結果が0の場合でも...
-
SQLでフィールドの順番を変更し...
-
JOINで1つのテーブルに空白があ...
-
SQLについて教えて下さい with(...
-
'internal' のシステム メモリ...
-
SQL server改行コード
-
グループ毎の最大値を持つデー...
-
SQLServerでの切り上げ処理
-
「重複を間引いた数」をcountし...
-
SQL Server 2005 Express で CD...
-
自作関数の方がパフォーマンス...
-
uniqueキーをupdateで+1するとE...
-
DB2でのロック
-
効率の良い検索方法が分かりま...
-
MySQLで複数のSELECT文を1文に...
-
結合? コピー? 初歩的な質...
-
外部結合での"OR"文
-
SQLでの計算結果がおかしい
-
★Mysql ある日程から10日後以降...
おすすめ情報