オブジェクト(ツリー,マップ)、配列を行へ展開する。
成果物
オブジェクトを行にする
ターミナルで以下コマンドを実行する。
sqlite3
対話モードにて以下コマンドをコピペし実行。
create table users(id int primary key, json text); insert into users values(1, '{"id": 1, "name": "yamada", "class": "A"}'); insert into users values(2, '{"id": 2, "name": "suzuki", "class": "B"}'); insert into users values(3, '{}'); .headers on .mode column select * from users, json_tree(users.json);
id json key value type atom id parent fullkey path ---------- ----------------------------------------- ---------- ------------------------------------ ---------- ---------- ---------- ---------- ---------- ---------- 1 {"id": 1, "name": "yamada", "class": "A"} {"id":1,"name":"yamada","class":"A"} object 0 $ $ 1 {"id": 1, "name": "yamada", "class": "A"} id 1 integer 1 2 0 $.id $ 1 {"id": 1, "name": "yamada", "class": "A"} name yamada text yamada 4 0 $.name $ 1 {"id": 1, "name": "yamada", "class": "A"} class A text A 6 0 $.class $ 2 {"id": 2, "name": "suzuki", "class": "B"} {"id":2,"name":"suzuki","class":"B"} object 0 $ $ 2 {"id": 2, "name": "suzuki", "class": "B"} id 2 integer 2 2 0 $.id $ 2 {"id": 2, "name": "suzuki", "class": "B"} name suzuki text suzuki 4 0 $.name $ 2 {"id": 2, "name": "suzuki", "class": "B"} class B text B 6 0 $.class $ 3 {} {} object 0 $ $
なぜかid
が2つ出てくる。しかもselect id
すると後ろのid
しか取れない。前のほうのid
が取れない。おそらく前のは行番号、後ろのは列番号。列番号はなぜ偶数になるのか不明。列はkey
とvalue
という2値の組合せだから?
ツリーでみてみると、リーフはkey
値がある。ノードはkey
値がない。
json_treeテーブル
json_tree()
関数はjson_tree
という名のテーブルを返す。
fullkey
+ json_extract
fullkey
を元にしてjson_extract
関数にて展開してみる。
select key, json_extract(json, fullkey) from (select * from users, json_tree(users.json));
key json_extract(json, fullkey) ---------- ------------------------------------ {"id":1,"name":"yamada","class":"A"} id 1 name yamada class A {"id":2,"name":"suzuki","class":"B"} id 2 name suzuki class B {}
行番号を追加する。
select rowid, key, json_extract(json, fullkey) from (select * from (select rowid, json from users) as users, json_tree(users.json));
rowid key json_extract(json, fullkey) ---------- ---------- ------------------------------------ 1 {"id":1,"name":"yamada","class":"A"} 1 id 1 1 name yamada 1 class A 2 {"id":2,"name":"suzuki","class":"B"} 2 id 2 2 name suzuki 2 class B 3 {}
列データのみに絞り込む。
select rowid, key, json_extract(json, fullkey) from (select * from (select rowid, json from users) as users, json_tree(users.json) where key!='');
rowid key json_extract(json, fullkey) ---------- ---------- --------------------------- 1 id 1 1 name yamada 1 class A 2 id 2 2 name suzuki 2 class B
これで行における列を特定できるデータが揃った。
name='yamada'
の行番号は何か
名前で行を特定する。
select rowid from (select rowid, key, json_extract(json, fullkey) as value from (select * from (select rowid, json from users) as users, json_tree(users.json) where key!='')) where key='name' and value='yamada';
副問合せ地獄。インデントを含めたコードは以下。
select rowid from ( select rowid, key, json_extract(json, fullkey) as value from ( select * from ( select rowid, json from users ) as users, json_tree(users.json) where key!='' ) ) where key='name' and value='yamada';
実行結果は以下。
rowid ---------- 1
name='yamada'
のclass
は何か
select value from ( select rowid, key, json_extract(json, fullkey) as value from ( select * from ( select rowid, json from users ) as users, json_tree(users.json) where key!='' ) ) where key='class' and rowid = ( select rowid from ( select rowid, key, json_extract(json, fullkey) as value from ( select * from ( select rowid, json from users ) as users, json_tree(users.json) where key!='' ) ) where key='name' and value='yamada' );
なんと4重の副問合せ。しかも最上位のfrom
とwhere
にある副問合せはほとんど重複している。これを重複なく書けないものか。
実行結果は以下。
value ---------- A
情報源
対象環境
- Raspbierry pi 3 Model B+
- Raspbian stretch 9.0 2018-11-13
- bash 4.4.12(1)-release
- SQLite 3.29.0
$ uname -a Linux raspberrypi 4.19.42-v7+ #1218 SMP Tue May 14 00:48:17 BST 2019 armv7l GNU/Linux
前回まで
- SQLite3学習をはじめよう
- SQLite3学習 SQLiteについて
- SQLite3学習 SQLiteの適切な用途
- SQLite3学習 SQLiteの特徴
- SQLite3学習 SQLiteのクセ
- SQLite3学習 データ型とアフィニティ
- SQLite3学習 演算子の一覧
- SQLite3学習 よくある質問
- SQLite3学習 SQLiteダウンロード&コンパイル
- SQLite3学習 Tclで操作する
- SQLite3学習 ビルドオプション動作確認(SQLITE_ALLOW_URI_AUTHORITY)
- SQLite3学習 面白そうなコンパイルオプション
- SQLite3学習 SQLiteの拡張について
- SQLite3学習 JSON拡張
- SQLite3学習 JSON拡張(json_extract)
- SQLite3学習 JSON拡張(json_each)