テーブルを作らずにクエリをちょっと試す

あるクエリがどんな動きをするのかを手を動かしながら探索的に調べたいときに、テーブルを作らずにCTE(Common Table Expression)を使ってデータを作ればはかどるんじゃないだろうかと思った。

たとえばこれはSQLアンチパターンにでてくるクエリだけど。

SELECT * FROM Bugs
  JOIN Tags AS t1 USING (bug_id)
  JOIN Tags AS t2 USING (bug_id)
WHERE t1.tag = 'printing' AND t2.tag = 'performance';

これがどんな動きをするのかを、テーブルを作らずにCTEを使って実行してみる。まずそのまま実行すると、

=> SELECT * FROM Bugs
  JOIN Tags AS t1 USING (bug_id)
  JOIN Tags AS t2 USING (bug_id)
WHERE t1.tag = 'printing' AND t2.tag = 'performance';
ERROR:  relation "bugs" does not exist
LINE 1: SELECT * FROM Bugs

当然エラーとなる。Bugsが無いのでWITH句を使って適当に作ろう。

=> WITH Bugs AS (
    VALUES (1)
)
SELECT * FROM Bugs
  JOIN Tags AS t1 USING (bug_id)
  JOIN Tags AS t2 USING (bug_id)
WHERE t1.tag = 'printing' AND t2.tag = 'performance';
ERROR:  relation "tags" does not exist
LINE 5:   JOIN Tags AS t1 USING (bug_id)

今度はTagsが無い。

=> WITH Bugs AS (
    VALUES (1)
),
Tags AS (
    VALUES (1)
)
SELECT * FROM Bugs
  JOIN Tags AS t1 USING (bug_id)
  JOIN Tags AS t2 USING (bug_id)
WHERE t1.tag = 'printing' AND t2.tag = 'performance';
ERROR:  column "bug_id" specified in USING clause does not exist in left table

両方のテーブルにbug_idが必要だ。

=> WITH Bugs(bug_id) AS (
    VALUES (1)
),
Tags(bug_id) AS (
    VALUES (1)
)
SELECT * FROM Bugs
  JOIN Tags AS t1 USING (bug_id)
  JOIN Tags AS t2 USING (bug_id)
WHERE t1.tag = 'printing' AND t2.tag = 'performance';
ERROR:  column t1.tag does not exist
LINE 10: WHERE t1.tag = 'printing' AND t2.tag = 'performance';

Tags.tagが必要だ。

=> WITH Bugs(bug_id) AS (
    VALUES (1)
),
Tags(bug_id, tag) AS (
    VALUES (1, 'printing')
)
SELECT * FROM Bugs
  JOIN Tags AS t1 USING (bug_id)
  JOIN Tags AS t2 USING (bug_id)
WHERE t1.tag = 'printing' AND t2.tag = 'performance';
 bug_id | tag | tag
--------+-----+-----
(0 rows)

OK。エラーはなくなった。後は値を工夫すればいい。

=> WITH Bugs(bug_id, summary) AS (
    VALUES
    (1, 'bug 1'),
    (2, 'bug 2'),
    (3, 'bug 3'),
    (4, 'bug 4')
),
Tags(bug_id, tag) AS (
    VALUES
    (1, 'printing'),
    (1, 'performance'),
    (2, 'printing'),
    (3, 'performance')
)
SELECT * FROM Bugs
  JOIN Tags AS t1 USING (bug_id)
  JOIN Tags AS t2 USING (bug_id)
WHERE t1.tag = 'printing' AND t2.tag = 'performance';
 bug_id | summary |   tag    |     tag
--------+---------+----------+-------------
      1 | bug 1   | printing | performance
(1 row)

データとクエリが1つになるので試行錯誤の過程を記録しやすそうだ。

あと、この方法はテーブルが存在する場合もWITH句を優先してくれるので、たとえば実際にはBugsが100万行くらいあるんだけど5行くらいで試したい、みたいなこともできる。

2018年はこんな年でした

英語学習の動画いろいろ見たけどこれが一番お気に入りです。

www.youtube.com

もっと前はこんな年でした

Windows10の新フォント「UDデジタル教科書体」をブラウザで使ってみる

ちょっと前の話だけど、Windows 10 Fall Creators Updateでフォントが追加された。

forest.watch.impress.co.jp

で、UDデジタル教科書体 NK-Rをブラウザのデフォルトのフォントにしてみた。 ちなみに使っているのはSurface Pro 4で解像度は2736 x 1824、スケーリングは200%。ブラウザはFirefox Developer Editionです。

f:id:iakio:20180206190717p:plain

長いドキュメントを読むときはなかなか良いと思う。

f:id:iakio:20180206192633p:plain

あと書くときも良い。なんというか、ちょっと違った気分になる。

他のフォントと混ざったとき、最初は違和感があったけどだんだん気にならなくなってきた。

f:id:iakio:20180206190749p:plain

2017年はこんな年でした

あと適当に動画貼っておきます。 www.nicovideo.jp

もっと前はこんな年でした

PostgreSQL勉強会@札幌で発表してきました

SQLを実行したときに、PostgreSQLはどのようにデータにアクセスしているのか」というタイトルで発表してきました。

jpug-ezo.connpass.com

ほとんどデモだけなので、発表資料はありません。

データベースって、ただ単にデータを読んだり書いたりするだけのものなのに、それを何十年も作り続けている人たちがいて、 PostgreSQLに関して言えば毎年メジャーバージョンアップをしてるわけです。

その裏側にはものすごくいろいろな工夫があって、自分はそれをソースコードを読んで、頭の中で動きを想像して面白いなーって思うんだけど、 データベースが動くところが目に見えれば、もっと面白いんじゃないかなあ、という感じの発表でした。

autovacuumが動いてほしいときにはなかなか動かなくて、余計な時に動くという古典的なコントみたいな展開も手伝って、 予想以上に楽しんでもらえたように思います(ポカーンだったらどうしようと思ってました)。

最後にFILLFACTORを設定しないテーブルと設定したテーブルの比較をしたのですが、 懇親会で @kkkida_twtr さんに、FILLFACTOR設定した方ではHOTが効いてインデックスが更新されていなかったはずということを教えてもらって、 めっちゃその説明すればよかった!と思いました。

当日の様子は#jpugezoで多少感じられるかもしれません。

#jpugezo - Twitter Search

2016年はこんな年でした

取りあえず今年一番言いたいことは、これ本当にいい話なのでみんな見てほしいということです。 今年というかここ数年で一番のスライド。

speakerdeck.com

あと適当に動画貼っておきます。

www.nicovideo.jp

www.nicovideo.jp

もっと前はこんな年でした

「基本からしっかり学ぶ Symfony2 入門」メモ(3)

「基本からしっかり学ぶ Symfony2 入門」を買った。

基本からしっかり学ぶ Symfony2入門

基本からしっかり学ぶ Symfony2入門

基本からしっかり学ぶ Symfony2入門:書籍案内|技術評論社

hidenorigoto/symfony2-book: 基本からしっかり学ぶSymfony2入門 サポートサイト

Writer::createFromStringの引数について

前回、Write::createFromString('', '')の引数は2つだったと書いたけど、その意味を見ていなかった。第二引数はv7.0では改行コードだったが、v8.0では削除され引数は1つになったようだ。

8-3 独自のサービスの定義

debug:containerでエラーとなった。

> php.exe C:\Users\ishida\PhpstormProjects\classic-symfony\bin\console debug:container app.inquiry_csv_builder


  [Symfony\Component\DependencyInjection\Exception\InvalidArgumentException]
  The file "C:\Users\ishida\PhpstormProjects\classic-symfony\src\AppBundle\De
  pendencyInjection/../Resources/config\services.yml" does not contain valid
  YAML.



  [Symfony\Component\Yaml\Exception\ParseException]
  The reserved indicator "@" cannot start a plain scalar; you need to quote t
  he scalar at line 7 (near "arguments: [%csv_encoding%, @app.inquiry_reposit
  ory]").

'@app.inquiry_repository'とシングルクォートで囲む必要があった。

8-4 独自の設定値の定義

この本の山場であり、Symfonyの最大の特徴ではないかと思う。

MemberjoinedDate@var \DateTimeとなっているがstringなのでは?

prototypeがわからない。

    members:
        山田: {part: トランペット, joinedDate: "2010-10-01"}
        田中: {part: バイオリン, joinedDate: "2008-04-10"}

同じようなものを繰り返す時に使うということか。

例えばこれを

    members:
        - {name: 山田, part: トランペット, joinedDate: "2010-10-01"}
        - {name: 田中, part: バイオリン, joinedDate: "2008-04-10"}

と書くこともできるのだろうか。

できた。

https://github.com/iakio/classic-symfony/commit/d9f4e70820c180996ec9b8704290f450e5893d73

でも一意な識別子がある場合は元の書き方の方が良さそうだ。