Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Nippondanji氏に怒られても仕方ない、配列型とJSON型の使い方

2,382 views

Published on

PostgreSQLの配列型とJSON型を使うと、1:N を 1:N のまま取り出せるよ、という話。
なお、氏からは「分かって使うなら怒らないよ」とコメントいただきました。
(理論から学ぶデータベース実践入門Night LT)

Published in: Technology
  • Be the first to comment

Nippondanji氏に怒られても仕方ない、配列型とJSON型の使い方

  1. 1. Nippondanji 氏に 怒られても仕方ない 配列型とJSON型の 使い方 (in PostgreSQL) Makoto Kuwata http://www.kuwata-lab.com/ https://github.com/kwatch/ 理論から学ぶデータベース実践入門Night LT
  2. 2. copyright 2015 kuwata-lab.com all rights reserved.© 配列型とは? 複数の値を持てるデータ型 集合と違い、順番を保持できるのがポイント >> select '{34.6582, 139.7020}'::float[]; float8 ------------------ {34.6582,139.702} (1 row) floatの配列型 へのキャスト '{ }' が配列の リテラル
  3. 3. copyright 2015 kuwata-lab.com all rights reserved.© JSON型とは? JSONデータを保持できるデータ型 キーと値の組や、構造が不定なデータが保存できる >> select '{"type":"string", "required":true}'::json; json ------------------------------------ {"type":"string", "required":true} (1 row) JSON型 へのキャスト
  4. 4. copyright 2015 kuwata-lab.com all rights reserved.© なんで怒られちゃうの? 第一正規化を平然と無視してるから >> create table bookmark ( id serial primary key , url text not null , title text not null , tags text[] ); >> select * from bookmark; id | url | title | tags ----+---------------------+---------+----------------- 1 | https://example.com | Example | {'news','game'} (1 row) 1つのカラムに複数の値! しかも順序つき!
  5. 5. copyright 2015 kuwata-lab.com all rights reserved.© 話は変わって、サンプルデータ ID Name 101 T-Shirt 102 Sweater Product ID Color Code 101 White W 101 Black B 102 White WH 102 Ivory IV 102 Gray GR product テーブル coloring テーブル
  6. 6. copyright 2015 kuwata-lab.com all rights reserved.© joinすると… ID Name Code Color 101 T-Shirt W White 101 T-Shirt B Black 102 Sweater WH White 102 Sweater IV Ivory 102 Sweater GR Gray from product join coloring on product.id = coloring.product_id
  7. 7. copyright 2015 kuwata-lab.com all rights reserved.© でも欲しいのは… ID Name (Code, Color) 101 T-Shirt (W, White) (B, Black) 102 Sweater (WH, White) (IV, Ivory) (GR, Gray) 1 : N の関係を保ったまま結果を取り出したい 1 : N の形で取得したい
  8. 8. copyright 2015 kuwata-lab.com all rights reserved.© join >> select product.id, product.name, c.color from product left join coloring c on product.id = c.product_id ; id | name | color -----+---------+------- 101 | T-Shirt | White 101 | T-Shirt | Black 102 | Sweater | White 102 | Sweater | Ivory 102 | Sweater | Gray (5 rows) これがうれしくない
  9. 9. copyright 2015 kuwata-lab.com all rights reserved.© 集約関数 array_agg() >> select product.id, product.name, coloring.color , array_agg(c.color) as colors from product left join coloring c on product.id = c.product_id group by product.id, product.name ; id | name | colors -----+---------+-------------------- 101 | T-Shirt | {White,Black} 102 | Sweater | {White,Ivory,Gray} (2 rows) 複数の値を配列型で取得! 1 : N で取り出せてる!
  10. 10. copyright 2015 kuwata-lab.com all rights reserved.© 行コンストラクタ >> select product.id, product.name , array_agg((c.code, c.color)) as colors from product left join coloring c on product.id = c.product_id group by product.id, product.name ; id | name | colors -----+---------+---------------------------------------- 101 | T-Shirt | {"(W,White)","(B,Black)"} 102 | Sweater | {"(WH,White)","(IV,Ivory)","(GR,Gray)"} (2 rows) または row(c.code, c.color) 行の配列だけど パースが必要になる
  11. 11. copyright 2015 kuwata-lab.com all rights reserved.© 集約関数 json_agg() >> select product.id, product.name , json_agg((c.code, c.color)) as colors from product left join coloring c on product.id = c.product_id group by product.id, product.name ; id | name | colors -----+---------+----------------------------- 101 | T-Shirt | [{"f1":"W","f2":"White"}, + | | {"f1":"B","f2":"Black"}] 102 | Sweater | [{"f1":"WH","f2":"White"}, + | | {"f1":"IV","f2":"Ivory"}, + | | {"f1":"GR","f2":"Gray"}] (2 rows) キーが f1, f2, ... に なってしまう ;(
  12. 12. copyright 2015 kuwata-lab.com all rights reserved.© 複合型 >> create type code_name as (code text, name text); >> select product.id, product.name , json_agg((c.code, c.color)::code_name) as colors from product left join coloring c on product.id = c.product_id group by product.id, product.name; id | name | colors -----+---------+--------------------------------- 101 | T-Shirt | [{"code":"W","name":"White"}, + | | {"code":"B","name":"Black"}] 102 | Sweater | [{"code":"WH","name":"White"}, + | | {"code":"IV","name":"Ivory"}, + | | {"code":"GR","name":"Gray"}] (2 rows) code_name型へ キャストすると キー名が設定される
  13. 13. copyright 2015 kuwata-lab.com all rights reserved.© 相関サブクエリ >> select product.id, product.name , ( select json_agg(t.*) from ( select code, color from coloring c2 where c2.product_id = product.id ) as t ) as colors from product left join coloring c on product.id = c.product_id group by product.id, product.name ; ...(前ページと同じ結果なので省略)... うまくいくけど 三重の入れ子は 複雑すぎる…
  14. 14. copyright 2015 kuwata-lab.com all rights reserved.© 問題点 使いやすいとはとても言えない SQLごとに複合型を定義するわけにもいかないし、
 かといって相関サブクエリだと複雑すぎる DBドライバが配列型やJSON型に未対応 Python用以外は全滅に近い (PHPもRubyもJavaもダメ)、
 いったんtext型として取得してからパースする必要あり
  15. 15. copyright 2015 kuwata-lab.com all rights reserved.© 所感 配列型やJSON型を嫌う人は結構いる 第一正規化に反するので、気持ちはわかる クエリ結果に使うのはいいんじゃない? 大事なのはテーブルが正規化されていることであり、
 クエリ結果にまで同じことを求める必要はない 1 : N のまま取り出せるのはやはり便利 とても自然であり、本来あるべき姿
 (なぜ今まで出来なかったのか?)
  16. 16. copyright 2015 kuwata-lab.com all rights reserved.© 考察 我々が欲しいのはRelationalなのか? 欲しいのは速くて便利でトランザクションが使えるDBであり、 必ずしもRelationalである必要はない ID Name Code Color 101 T-Shirt W White 101 T-Shirt B Black 102 Sweate r WH White 102 Sweate r IV Ivory 102 Sweate r GR Gray ID Name Code,Color 101 T-Shirt (W, White) (B, Black) 102 Sweater (WH, White) (IV, Ivory) (GR, Gray) 正直、tupleの集合より 木構造のほうが便利やで こんなこと言ってたら 怒られても仕方ない
  17. 17. copyright 2015 kuwata-lab.com all rights reserved.© まとめ 配列型とJSON型の集約関数を使うと、
 1 : N を 1 : N のまま取り出せるよ! array_agg() と json_agg() 現状では使いやすくはない 複合型の定義も相関サブクエリもしんどい、
 DBドライバの対応状況はもっとしんどい
  18. 18. copyright 2015 kuwata-lab.com all rights reserved.© PostgreSQLに興味がわいたら 2015-11-27(Fri) 詳細は「ポスグレ カンファレンス 2015」でggr 公式バナーなのに「e」が抜けているけど たぶんデザイナーじゃない人が作ってるし 大目に見てあげて!
  19. 19. copyright 2015 kuwata-lab.com all rights reserved.© 使い方 より 作り方 を知りたいなら 内部構造から学ぶPostgreSQL ̶ 設計・運用計画の鉄則 ̶ 勝俣智成、佐伯昌樹、原田登志 技術評論社 2014-09-04
  20. 20. copyright 2015 kuwata-lab.com all rights reserved.© おしまい

×