Ce diaporama a bien été signalé.
Nous utilisons votre profil LinkedIn et vos données d’activité pour vous proposer des publicités personnalisées et pertinentes. Vous pouvez changer vos préférences de publicités à tout moment.

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

2 656 vues

Publié le

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

Publié dans : Technologie
  • Soyez le premier à commenter

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.© おしまい

×