集約関数でorver
句を使ってみた。
成果物
データ
create table student_grades( class text, name text, point integer ); insert into student_grades values ('A', 'Adati', 53), ('A', 'Itou', 21), ('A', 'Uehara', 93), ('B', 'Kato', 82), ('B', 'Kida', 98), ('B', 'Kurihara', 66), ('B', 'Kei', 75), ('B', 'Koi', 75);
9ある集約関数にover
句を使ってみる。
avg
select avg(point) over (order by class), class, name, point from student_grades;
55.6666666666667|A|Adati|53 55.6666666666667|A|Itou|21 55.6666666666667|A|Uehara|93 70.375|B|Kato|82 70.375|B|Kida|98 70.375|B|Kurihara|66 70.375|B|Kei|75 70.375|B|Koi|75
できた。クラスごとの平均点。なぜかpartition by class
しなくてもいけた。
count
select count(*) filter(where 80<=point) over (order by class), class, name, point from student_grades;
1|A|Adati|53 1|A|Itou|21 1|A|Uehara|93 3|B|Kato|82 3|B|Kida|98 3|B|Kurihara|66 3|B|Kei|75 3|B|Koi|75
80点を超えた人数をクラスごとに、と思ったのだがB組おかしい。3
人でなく2
人では?
やはりパーティションをしっかりクラスにすべきか。
select count(*) filter(where 80<=point) over (partition by class order by point desc), class, name, point from student_grades;
1|A|Uehara|93 1|A|Adati|53 1|A|Itou|21 1|B|Kida|98 2|B|Kato|82 2|B|Kei|75 2|B|Koi|75 2|B|Kurihara|66
できた。一応、クラスごとに全レコードを含めてみる。
select count(*) filter(where 80<=point) over ( partition by class order by point desc groups between unbounded preceding and unbounded following ), class, name, point from student_grades;
1|A|Uehara|93 1|A|Adati|53 1|A|Itou|21 1|B|Kida|98 2|B|Kato|82 2|B|Kei|75 2|B|Koi|75 2|B|Kurihara|66
同じ。いまいちフレームの使い方がわからん。これ使わなくても集計できたのだが。
group_concat(X)
,(X,Y)
select class, name, point, group_concat(point) over ( partition by class order by point desc ) from student_grades;
A|Uehara|93|93 A|Adati|53|93,53 A|Itou|21|93,53,21 B|Kida|98|98 B|Kato|82|98,82 B|Kei|75|98,82,75,75 B|Koi|75|98,82,75,75 B|Kurihara|66|98,82,75,75,66
自分より前にある行の点数を結合したようだ。あ、はい、そうなるんですか。へぇ。よくわからんけど。いつ使うと、どう有効なの?
たぶん木構造とかで役立つ? と思ったがわからん。
create table T(id integer primary key, name text, parent integer); insert into T values (1, 'root', 0), (2, 'n1', 1), (3, 'n2', 1), (4, 'n11', 2); select id, name, group_concat(name, '/') over (order by id) from T;
1|root|root 2|n1|root/n1 3|n2|root/n1/n2 4|n11|root/n1/n2/n11
ぜんぜん違う。親が同じのをピアにしても仕方ないし。
id
とparent
が一致したら親子。それを抽出できないか?
select id, name, group_concat(name, '/') filter (id = parent) over (order by id) from T;
1|root| 2|n1| 3|n2| 4|n11|
違いますね、はい。これはたぶん同一行のid
とparent
の一致確認しているのだろう。ダメだ、まるで理解できてない。
max
select max(point) over (partition by class order by point desc), class, name, point from student_grades;
93|A|Uehara|93 93|A|Adati|53 93|A|Itou|21 98|B|Kida|98 98|B|Kato|82 98|B|Kei|75 98|B|Koi|75 98|B|Kurihara|66
min
select min(point) over (partition by class order by point desc), class, name, point from student_grades;
93|A|Uehara|93 53|A|Adati|53 21|A|Itou|21 98|B|Kida|98 82|B|Kato|82 75|B|Kei|75 75|B|Koi|75 66|B|Kurihara|66
おや? それぞれ自分の行が出ている。たぶんフレームだな。
select min(point) over ( partition by class order by point desc groups between unbounded preceding and unbounded following ), class, name, point from student_grades;
21|A|Uehara|93 21|A|Adati|53 21|A|Itou|21 66|B|Kida|98 66|B|Kato|82 66|B|Kei|75 66|B|Koi|75 66|B|Kurihara|66
並び順が昇順、降順、どちらであっても、クラス内の最大・最小を求めたいなら、フレーム定義しておくべき。ということかな?
sum()
, total()
select sum(point) over (partition by class order by point desc), class, name, point from student_grades;
93|A|Uehara|93 146|A|Adati|53 167|A|Itou|21 98|B|Kida|98 180|B|Kato|82 330|B|Kei|75 330|B|Koi|75 396|B|Kurihara|66
またおかしい。フレームを指定してみる。
select sum(point) over ( partition by class order by point desc groups between unbounded preceding and unbounded following ), class, name, point from student_grades;
167|A|Uehara|93 167|A|Adati|53 167|A|Itou|21 396|B|Kida|98 396|B|Kato|82 396|B|Kei|75 396|B|Koi|75 396|B|Kurihara|66
できた。やはりフレームの定義を適切にしておくべき場合があるようだ。省略したら現在行からそれ以前までの行になるのだろう。
もっとも、今回のようにクラス内合計点など求めても、あまり意味はないかもしれないが。
所感
窓関数の使い方や全体像のイメージがつかめない。使いこなせる気がまったくしない。フレームがよくわかってない。
対象環境
- Raspbierry pi 3 Model B+
- Raspbian stretch 9.0 2018-11-13
- bash 4.4.12(1)-release
- SQLite 3.29.0
- MeCab 0.996ユーザ辞書
$ uname -a Linux raspberrypi 4.19.42-v7+ #1218 SMP Tue May 14 00:48:17 BST 2019 armv7l GNU/Linux
前回まで
- SQLite3学習 俯瞰まとめ
- SQLite3学習 環境構築まとめ
- SQLite3学習 インタフェースまとめ(C言語、CLI、対話モード、Tcl...)
- SQLite3学習 ドットコマンドまとめ
- SQLite3学習 JSON拡張まとめ
- SQLite3学習 FTSまとめ(ICU, MeCab)
- SQLite3学習 再帰クエリ(WITH RECURSIVE)
- SQLite3学習 R-Treeモジュール
- SQLite3学習 Geopoly(2次元ベクタ画像の生成)
- SQLite3学習 拡張関数(generate_series)
- SQLite3学習 拡張ライブラリ数学関数(extension-functions.c)
- SQLite3学習 謎と名前
- SQLite3学習 構文まとめ
- SQLite3関数の一覧と分類
- SQLite3コア関数の一覧と分類
- SQLite3コア関数 quote
- SQLite3コア関数 lower,upper
- SQLite3コア関数 trim,ltrim,rtrim
- SQLite3コア関数 replace
- SQLite3コア関数 glob
- SQLite3コア関数 like
- SQLite3コア関数 printf
- SQLite3コア関数 substr
- SQLite3コア関数 length
- SQLite3コア関数 instr
- SQLite3コア関数 unicode,char
- SQLite3コア関数 soundex
- SQLite3コア関数 likelihood,likely,unlikely
- SQLite3コア関数 abs
- SQLite3コア関数 max,min
- SQLite3コア関数 random
- SQLite3コア関数 round
- SQLite3コア関数 hex
- SQLite3コア関数 randomblob
- SQLite3コア関数 zeroblob
- SQLite3コア関数 ifnull,nullif,coalesce
- SQLite3コア関数 changes,total_changes,last_insert_rowid
- SQLite3コア関数 typeof
- SQLite3コア関数 load_extension
- SQLite3コア関数 sqlite_*
- SQLite3日時関数(date,time,datetime,julianday,strftime)とcurrent_date,current_time,current_timestamp
- SQLite3集計関数(avg,count,group_concat,max,min,sum,total)
- SQLite3窓関数
- SQLite3構文 窓関数
- SQLite3窓関数 窓関数はover句を省略するとエラーになる(Error: misuse of window function *)