blog

MySQLのランキング関数の実装

今、すべての学生のスコアをランク付けし、ランキングをリストする必要があります。私はちょうどこの需要を見て、私は少し混乱している、アイデアがない、なぜそれが少し需要に困難である、私はインターネットに情報...

Mar 4, 2020 · 5 min. read
シェア

今、すべての学生のスコアをランク付けし、ランクをリストする要件があります。私はちょうどこの要件を見た、私は少し混乱している、全くアイデアがありません、なぜそれが難しい少し要件、私はそれを行うことはありません情報を確認するためにインターネットに移動し、すべての実装をリストアップし、それらのすべてを学ばなければなりません。

データベースの準備

スコアテーブルの作成 s_score

CREATE TABLE `s_score` (
 `id` int NOT NULL AUTO_INCREMENT,
 `score` int NOT NULL DEFAULT 0,
 `name` varchar(20) CHARACTER SET utf8mb4 NULL,
 PRIMARY KEY (`id`)
);

データ挿入

INSERT INTO `s_score` (`name`, `score`) VALUES
(' , 80),
(' , 90),
(' , 60),
(' , 70),
(' , 80),
(' , 87),
(' , 69),
(' , 69),
(' , 91),
(' , 96),
(' , 96),
(' , 80),
(' , 88);

一般的な実装

ランク関数 RANK は、この要件を完全にサポートするために MySQL 8.0 で導入されましたが、MySQL 8.0 以上でサポートされている必要があります。 8.0 未満のバージョンで、ランクを記録するためにユーザ変数を使用してこれを実現する方法は何ですか。ユーザ変数:"@"で始まり、ユーザ変数とカラム名を区別するために"@var_name "という形式をとります。列が指定されていない限り、任意のランダムな複合スカラー式にすることができます。以下はユーザー変数の使い方の小さな例です。

select @a:=1 a,@b:=@a+1 b

実施結果

1 2

:=は代入を意味し、プログラミング言語の代入とは少し異なります。RANKランキング関数を実装するために単純なSQLを使用した場合の効果を以下に示します。

名前表示のためのユーザー変数の簡単な実装

SELECT name,score, @rank:=@rank+1 `rank` from s_score s,(select @rank:=0) q ORDER BY score desc
趙軍(1906-1986)中国共産党七大政治家の一人。 96 1
ワン・メイ(1905-1975)毛沢東の5番目の妻。 96 2
ジャック=ルイ・ダヴィッド(1748-1825)フランス新古典主義の画家 91 3
シャオロン 90 4
シャオロン 88 5
梁晨(1521-1564)明代の詩人 87 6
シャオフェイ(1955-)中国系アメリカ人小説家 80 7
張三 80 8
趙呉(前140-60)漢の外交官、政治家 80 9
李斯 70 10
ウィリアム 69 11
グリーン 69 12
リトルレッド 60 13

横並びランキング

今そこに別の問題は、同じスコア、サイドバイサイドランキングがあり、ランキングは同じでなければなりません。前のスコアの値を記録する一時変数を使用して、前のスコアが現在と等しいかどうかを判断し、等しい直接以前のランキング状況に戻り、それ以外の場合はランキング+ 1。

select name,score,case when @temp_score=score then @rank when @temp_score:=score then @rank:=@rank+1 END 
 `rank` from s_score s,(select @rank:=0,@temp_score:=NULL) q ORDER BY score desc
趙軍(1906-1986)中国共産党七大政治家の一人。 96 1
ワン・メイ(1905-1975)毛沢東の5番目の妻。 96 1
ジャック=ルイ・ダヴィッド(1748-1825)フランス新古典主義の画家 91 2
シャオロン 90 3
小明 88 4
シャオロン 87 5
シャオフェイ(1955-)中国系アメリカ人小説家 80 6
暁風 80 6
趙呉(前140-60)漢の外交官、政治家 80 6
暁風 70 7
ウィリアム 69 8
趙呉 69 8
趙呉 60 9

横並びランキングスキップ

1位が同点の場合、次の順位は自動的にスキップされます。例えば、1位が2人同点の場合、91人が3位となり、人数に応じた順位となります。

SELECT name,score,rank from (
SELECT name ,score,@rank :=IF( @temp_score = score, @rank, @rank_incr ) `rank`,@rank_incr := @rank_incr + 1,
	@temp_score := score FROM score s,(SELECT@rank := 0,@temp_rank := NULL,@rank_incr := 1 ) q ORDER BY score DESC) a
趙軍(1906-1986)中国共産党七大政治家の一人。 96 1
ワン・メイ(1905-1975)毛沢東の5番目の妻。 96 1
ジャック=ルイ・ダヴィッド(1748-1825)フランス新古典主義の画家 91 3
シャオロン 90 4
シャオロン 88 5
梁晨(1521-1564)明代の詩人 87 6
シャオフェイ(1955-)中国系アメリカ人小説家 80 7
張三 80 7
趙呉(前140-60)漢の外交官、政治家 80 7
張三 70 10
ウィリアム 69 11
グリーン 69 11
グリーン 60 13

SQLウィンドウ関数の使用

ウィンドウ関数の基本構文は以下の通りです:

ソート関数/集計関数を選択

overの後にスペースがあることに注意してください。この構文はちょっと面倒で、うまく書けるまで何十回も試しました。ウィキペディアによると、ウィンドウ関数は現在のレコードとそれ以降のレコードの両方にアクセスできるようにします。ウィンドウ関数は、現在の行の周囲に所定の長さを持つ行または列を定義し、ウィンドウ内のデータセット全体で計算を実行します。ウィンドウはデータセットで、関数はデータの計算方法です。

partiton byはオプションです。partiton byを使用しない場合、テーブル全体をコレクションとし、最後にソート関数を使用して、ソート番号のソート順序に従って各レコードを取得します。ソート関数は、主にrank()、dense_rank、row_number、それらの主な違いです:

  • rank():同じフィールドをソートし、同点の場合は並列にランク付けされ、ランク差が生じます。
  • dense_rank():同じフィールドをソートし、同じ現象が発生した場合に同順位となる、連続した順位
  • row_number():同じフィールドを並べ替えると、ランクがリンクされている、同じがある場合でも、並んでランクされません
	select name,score, RANK() over (ORDER BY score DESC) `rank`,ROW_NUMBER() over (order by score DESC) `row`,
	DENSE_RANK()over (ORDER BY score DESC) `dense` from s_score
	
趙軍(1906-1986)中国共産党七大政治家の一人。 96 1 1 1
ワン・メイ(1905-1975)毛沢東の5番目の妻。 96 1 2 1
ジャック=ルイ・ダヴィッド(1748-1825)フランス新古典主義の画家 91 3 3 2
シャオロン 90 4 4 3
小明 88 5 5 4
シャオロン 87 6 6 5
趙呉(前140-60)漢の外交官、政治家 80 7 7 6
シャオフェイ(1955-)中国系アメリカ人小説家 80 7 8 6
暁風 80 7 9 6
暁風 70 10 10 7
張三 69 11 11 8
ウィリアム 69 11 12 8
趙呉 60 13 13 9
Read next

デザインパターンの学び方

「オレンジは淮南で生まれればオレンジであり、オレンジは華北で生まれればハリネズミである」--サーバーサイドのアプリケーションシナリオでは合理的で便利でクールに見える操作でも、フロントエンドのシナリオに適用すると失敗することがあります。本書の目的は、従来のデザインパターン本の「翻訳」ではなく、フロントエンドエンジニアにデザインパターンの入門書を提供することです。

Mar 4, 2020 · 3 min read