JUST FOR FUN

Twitter:@okwra Facebook:ayato.ookawara GitHub:@tearon4 other:@taiga006

「みんなの家。 -建築家一年生の初仕事- 」(光嶋裕介・著)を読んだ。

久しぶりの読書の話です。

久しぶりに建築の話です。 

みんなの家。建築家一年生の初仕事
みんなの家。建築家一年生の初仕事
 

 

ドイツ・ベルリンの設計事務所での仕事から帰国して独立したばかりだった建築家の光嶋裕介氏が、ひょんなきっかけからチャンスがやって来た思想家・文化学教授の内田樹氏の自宅を建てるまでの出来事をまとめた本です。

 

「1階が合気道の道場兼、能舞台兼、寺子屋のパブリックスペース。2階が仲間と麻雀をしたり語り合えるようなセミパブリックスペースとプラベートスペースが融合した空間」

武家屋敷のような家にしたい。」

 

この一件無理難題とも言える注文に、建築家1年生(更地からの一軒家建設については当時、初体験だった)光嶋裕介氏がいかに答えていくのか?が主なストーリーです。

 

読み終わって感じるのはアベンジャーズ感とでもいうのか...あるいはワンピース的なものと言えばいいのか...とにかくこの凱風館(内田氏の自邸の名前)はいろんな職人たちが協力して、プロとプロの技が融合してできている。そのことが最高にカッコいい、ということです。 

そして何よりチームの最年少にして「凱風館」建築事業におけるマエストロ(本の中で建築とオーケストラは似ていると書かれています)である光嶋氏のものづくりに対する熱い気持ちがビンビンに感じられます。

 

「ものづくりに対する熱い気持ち」という一見曖昧な言葉はどこから感じられたのか、というとそれは随所に出てくる光嶋氏の各職人への多大なる信頼(リスペクト)です。

 

施工者、構造設計者、大工、左官、瓦職人、テキスタイル・デザイン・コーディネーター、画家...

 

建築家は万能人間ではない、一介のアイデアマンであり、実際に手を動かして家を建てていく人たち無くして価値はない(何より圧倒的現場経験が少ない)。門外漢なので多少表現が過大であれど、そのことを踏まえた上で光嶋氏が持つ「絶対に最高の家を建てたい!」という一貫した強い気持ちが読者を引き込み、奮い立たせてくれます。

 

何より仕事を楽しんでいるのが素敵。そうそうこの本にはいわゆる苦労話みたいなものがほとんど出てきません。普通、自分が初めて一軒家を建てるってなったら絶対ミスもするし、人とぶつかることだってあると思います。いや、実際「凱風館」を建てるにあたっても絶対その辺の話はあったはずなのに本書にはほとんど出てきません。

 

それ以上の仕事への愛、共に作る職人たちへの愛のほうが文章にする価値があったのでしょう。

 

それと同時に本当に「縁」というのは大事なんだなー、と感じる本でもありました。ここでいう「縁」というのは本当に偶然の、まさに「運」的な要素を含む一方で、自分がから掴みにいく(そもそもこの凱風館の設計話は光嶋氏が大学の講義で出会った山本浩二画伯に声をかけられて参加した麻雀の場で当時憧れていた内田氏に「建築家としてなんでもやります!」とアピールしたところから始まる)「精神」それこそが大事なんだなー、と。「運」は巡り巡ってやってきたりやってこなかったりするけど「精神」は普段から自分を磨かない限り強くはならない、いざというときに縁を掴みとれない。

 

まだまだ先ですが、いつか自分が家を建てることがあったらぜひこういう人に家を建ててもらいたい、いや一緒に建てたい!なんて夢をもたせてくれる、そんな2018年読んでよかった本ノミネート作品でした。以上。

 

f:id:taiga006:20180604201342p:plain

f:id:taiga006:20180604201345p:plain

f:id:taiga006:20180604201630p:plain

 (中島工務店サイトより)

神戸市・凱風館 | 作品集

 

みんなの家。建築家一年生の初仕事

みんなの家。建築家一年生の初仕事

 

 

 

(2018.6.5 加筆修正)

 お名前修正させていただきました…。ごめんなさい…。

クロス結合(CROSS JOIN)が役に立つケースに初めてぶつかった。(横持ち⇔縦持ち変換)

話を始める前にまずは簡単によく使うSQLの結合公文を復習していきます。

- INNER JOIN (内部結合)
- LEFT OUTER JOIN (左外部結合)
- RIGHT OUTER JOIN (右外部結合)
- FULL OUTER JOIN (完全外部結合)

このままの形式で書くことはあまりありません。基本的に

- INNER JOIN ⇒ JOIN
- LEFT OUTER JOIN ⇒ LEFT JOIN
- RIGHT OUTER JOIN ⇒ RIGHT JOIN

といった省略形で書くことが多いです。

LEFT JOINとRIGHT JOINがなんなのか最初に掴むまで苦労しましたが、いくつか手で書いてみるとわかります。

ここに雑な例を載せておきます。

mysql> SELECT * FROM photobook;
+------+-----------------------+-----------------+------------+-------------+
| id   | title                 | name            | date       | circulation |
+------+-----------------------+-----------------+------------+-------------+
|    1 | パスポート            | 白石麻衣        | 2017-02-07 |      273580 |
|    2 | やさしい棘            | 橋本奈々未      | 2015-08-28 |       66125 |
|    3 | 転調                  | 生田絵梨花      | 2016-01-21 |       84598 |
|    4 | 話を聞こうか。        | 衛藤美彩        | 2017-04-25 |       78821 |
+------+-----------------------+-----------------+------------+-------------+
4 rows in set (0.00 sec)

mysql> SELECT * FROM member;
+------+-----------------+------------+-------+
| id   | name            | age        | class |
+------+-----------------+------------+-------+
|    1 | 新内眞衣        | 1992-01-22 |     2 |
|    2 | 白石麻衣        | 1992-08-20 |     1 |
|    3 | 松村沙友理      | 1992-08-27 |     1 |
|    4 | 衛藤美彩        | 1993-01-04 |     1 |
|    5 | 伊藤かりん      | 1993-05-16 |     2 |
+------+-----------------+------------+-------+
5 rows in set (0.00 sec)

たとえばでこんなテーブルを準備。

実際にやってみましょう。

内部結合 JOIN( = INNER JOIN)

mysql> SELECT * FROM member INNER JOIN photobook USING (name);
+--------------+------+------------+-------+------+-----------------------+------------+-------------+
| name         | id   | age        | class | id   | title                 | date       | circulation |
+--------------+------+------------+-------+------+-----------------------+------------+-------------+
| 白石麻衣     |    2 | 1992-08-20 |     1 |    1 | パスポート            | 2017-02-07 |      273580 |
| 衛藤美彩     |    4 | 1993-01-04 |     1 |    4 | 話を聞こうか。        | 2017-04-25 |       78821 |
+--------------+------+------------+-------+------+-----------------------+------------+-------------+
2 rows in set (0.00 sec)

name というカラムで両者をつないでどっちにもあるものを引っ張ってきてます。

(余談だけどこの辺を解説しているサイトとか記事は結合因子を数値のカラムを使って見せるのでややこしく見えてしまう。上みたいに人名だったらどう結合されてるのかわかりやすい!...はず。)

左外部結合 LEFT JOIN

mysql> SELECT * FROM member LEFT JOIN photobook USING (name);
+-----------------+------+------------+-------+------+-----------------------+------------+-------------+
| name            | id   | age        | class | id   | title                 | date       | circulation |
+-----------------+------+------------+-------+------+-----------------------+------------+-------------+
| 白石麻衣        |    2 | 1992-08-20 |     1 |    1 | パスポート            | 2017-02-07 |      273580 |
| 衛藤美彩        |    4 | 1993-01-04 |     1 |    4 | 話を聞こうか。        | 2017-04-25 |       78821 |
| 新内眞衣        |    1 | 1992-01-22 |     2 | NULL | NULL                  | NULL       |        NULL |
| 松村沙友理      |    3 | 1992-08-27 |     1 | NULL | NULL                  | NULL       |        NULL |
| 伊藤かりん      |    5 | 1993-05-16 |     2 | NULL | NULL                  | NULL       |        NULL |
+-----------------+------+------------+-------+------+-----------------------+------------+-------------+
5 rows in set (0.01 sec)

ここでは向かって左側のテーブル、操作する主体のテーブルをmemberとしています。

そのため乃木坂年上5名の名前がちゃんと出てきます。

当然、新内眞衣松村沙友理伊藤かりんの写真集データは(ここでは)存在しないため、写真集部分のデータはNULLが入っています。

また逆に橋本奈々未生田絵梨花の写真集情報は参照されていないことがわかります。

右外部結合 RIGHT JOIN

mysql> SELECT * FROM member RIGHT JOIN photobook USING (name);
+-----------------+------+-----------------------+------------+-------------+------+------------+-------+
| name            | id   | title                 | date       | circulation | id   | age        | class |
+-----------------+------+-----------------------+------------+-------------+------+------------+-------+
| 白石麻衣        |    1 | パスポート            | 2017-02-07 |      273580 |    2 | 1992-08-20 |     1 |
| 衛藤美彩        |    4 | 話を聞こうか。        | 2017-04-25 |       78821 |    4 | 1993-01-04 |     1 |
| 橋本奈々未      |    2 | やさしい棘            | 2015-08-28 |       66125 | NULL | NULL       |  NULL |
| 生田絵梨花      |    3 | 転調                  | 2016-01-21 |       84598 | NULL | NULL       |  NULL |
+-----------------+------+-----------------------+------------+-------------+------+------------+-------+
4 rows in set (0.00 sec)

こちらは打って変わって操作の主体をphotobook側のテーブルとしています。

生田絵梨花橋本奈々未のrowがある一方で、彼女たちの年齢のデータはありません。なぜなら二人はmember テーブルに存在していないからです。

FULL OUTER JOINは説明していないけれど、実はMySQLでは実装されておらず、簡単に例示を示すことができません。
とはいえ、名前からだいたい察しが付くと思います。

左のテーブル(メインで操作するテーブル)にしかないものも表示するLEFT JOINと

右のテーブル(結合対象のテーブル)にしかないものも表示するRIGHT JOIN、

どちらも表示するのがFULL OUTER JOINだ、たぶん。(使ったことない。)

とまあ、雑ではあるが基本的なJOINの使い方は紹介できた気がします。

そして、ここからが今回の本題です。


クロス結合 (CROSS JOIN)とは何者だ?

ざっくり説明すると2つのテーブルを各データごとに結合してすべての組み合わせデータを取得する結合方法がクロス結合です。

何を言っているのかさっぱりだと思いますので、まとめていきます。

まずは次のようなテーブルを準備。

mysql> SELECT * FROM last_name;
+-------+-----------+
| group | last_name |
+-------+-----------+
|     1 | ITO       |
|     2 | SAITO     |
+-------+-----------+
2 rows in set (0.00 sec)

mysql> SELECT * FROM first_name;
+------+------------+-------+
| id   | first_name | group |
+------+------------+-------+
|    1 | かりん     |     1 |
|    2 | 理々杏     |     1 |
|    3 | 純奈       |     1 |
|    4 | 万理華     |     1 |
|    5 | 寧々       |     1 |
|    6 | 優里       |     2 |
|    7 | 飛鳥       |     2 |
|    8 | ちはる     |     2 |
+------+------------+-------+
8 rows in set (0.00 sec)

まずは先程も説明したINNER JOINを使うとどうなるか。

mysql> SELECT `group`, `last_name`, `first_name` FROM last_name JOIN first_name USING (`group`);
+-------+-----------+------------+
| group | last_name | first_name |
+-------+-----------+------------+
|     1 | ITO       | かりん     |
|     1 | ITO       | 理々杏     |
|     1 | ITO       | 純奈       |
|     1 | ITO       | 万理華     |
|     1 | ITO       | 寧々       |
|     2 | SAITO     | 優里       |
|     2 | SAITO     | 飛鳥       |
|     2 | SAITO     | ちはる     |
+-------+-----------+------------+
8 rows in set (0.00 sec)

特に引っかかることもないでしょう。

2つのテーブルのgroupカラムを使って等しいロウ同士を結合しています。

では、たとえば、(あくまでたとえば)ですが「この人はITO?それともSAITO?どっち?」みたいなクイズをやりたいとします。

(まあ、率直に言って「オタクを舐めるな」、って問題ですが…)

そんなときにCROSS JOINを使うとすべての組み合わせを見ることができます。

mysql> SELECT last_name.`group`, `last_name`, `first_name` FROM last_name CROSS JOIN first_name;
+-------+-----------+------------+
| group | last_name | first_name |
+-------+-----------+------------+
|     1 | ITO       | かりん     |
|     2 | SAITO     | かりん     |
|     1 | ITO       | 理々杏     |
|     2 | SAITO     | 理々杏     |
|     1 | ITO       | 純奈       |
|     2 | SAITO     | 純奈       |
|     1 | ITO       | 万理華     |
|     2 | SAITO     | 万理華     |
|     1 | ITO       | 寧々       |
|     2 | SAITO     | 寧々       |
|     1 | ITO       | 優里       |
|     2 | SAITO     | 優里       |
|     1 | ITO       | 飛鳥       |
|     2 | SAITO     | 飛鳥       |
|     1 | ITO       | ちはる     |
|     2 | SAITO     | ちはる     |
+-------+-----------+------------+
16 rows in set (0.00 sec)

こんな感じで先程まで説明してきた結合とは違い、どこかのカラムを参照して等しいとかではなく単純な組み合わせを計算(直積)しているわけです。そのため結合条件のUSINGやONは必要がありません。

結論から言うとクロス結合を実務で使う場面はそう多くないです。

現にここ半年ほど様々なクエリを書いてきましたが「CROSS JOINが必要だ!」と感じたことはありませんでした。

つい先日まで…。

今回どういうケースでクロス結合が必要となったのか。

それはズバリ言ってしまうと横持ちのデータを縦持ちに変換するケースです!!

(タイトルに書いてあるね\(^o^)/)

横持ちテーブルと縦持ちテーブル

f:id:taiga006:20180526212618p:plain

もはやダミーデータを準備するのも面倒になってしまったのでスクショで失礼します。

横持ちデータとは上のようないわゆるよく見るタイプのテーブル構造のデータの持ち方のこと。

一方で縦持ちテーブルは次のようなものです。

f:id:taiga006:20180526212651p:plain

おわかりいただけるでしょうか?

1行に対して1つの情報のみを格納しているのが縦持ちのデータ構造です。

後者は普段あまりみない上に一見メリットが無いように見えます。

しかし、たとえば横持ちのデータ構造で異様にカラム数が膨れ上がっているケースとか、あるいはデータがNULLばかりとか(スパースとかっていうらしい)のケースでは縦持ちにして整理したほうが格段に管理が楽になります。

それこそ今、上にスクショを張ったメンバー情報を管理するケースなどでは縦持ちの方が自然に感じます。(もちろん、あえてそういう例を選んでいます。)

とはいえ、常に「自然に感じる(=操作がしやすい)」状態でデータは保存されているとは限りません。

場合によっては臨機応変に縦持ち構造のデータを横持ち構造に、横持ち構造のデータを縦持ち構造に変換する必要があります。

では実際にまず、縦持ち⇒横持ちの変換を見てみましょう。

(こちらの変換ではCROSS JOINを使う必要はありません。)

mysql> select * from single;
+-----------------------------------------+-----------------+
| title                                   | center          |
+-----------------------------------------+-----------------+
| ぐるぐるカーテン                        | 生駒里奈        |
| おいでシャンプー                        | 生駒里奈        |
| 走れ!Bicycle                           | 生駒里奈        |
| 制服のマネキン                          | 生駒里奈        |
| 君の名は希望                            | 生駒里奈        |
| ガールズルール                          | 白石麻衣        |
| バレッタ                                | 堀未央奈        |
| 気づいたら片想い                        | 西野七瀬        |
| 夏のFree&Easy                           | 西野七瀬        |
| 何度目の青空か?                        | 生田絵梨花      |
| 命は美しい                              | 西野七瀬        |
| 太陽ノック                              | 生駒里奈        |
| 今、話したい誰かがいる                  | 西野七瀬        |
| 今、話したい誰かがいる                  | 白石麻衣        |
| ハルジオンが咲く頃                      | 深川麻衣        |
| 裸足でSummer                            | 齋藤飛鳥        |
| サヨナラの意味                          | 橋本奈々未      |
| インフルエンサー                        | 白石麻衣        |
| インフルエンサー                        | 西野七瀬        |
| 逃げ水                                  | 大園桃子        |
| 逃げ水                                  | 与田祐希        |
| いつかできるから今日できる              | 西野七瀬        |
| いつかできるから今日できる              | 齋藤飛鳥        |
| シンクロニシティ                        | 白石麻衣        |
+-----------------------------------------+-----------------+
24 rows in set (0.00 sec)

こんなデータを準備してみました。

さて早速実践してみたいと思うんですが、そのまえに今回はMySQLでの話なのでウィンドウ関数が使えません。(まあ最近のやつは使えるんだけど…)

ROW_NUMBERが使えないため、今回必要となる各メンバーが何枚センターを務めているのかを示す連番は自分でうまく計算してやらならければなりません。

先にその方法だけ示しておきます。

mysql> SET @num = 0;
Query OK, 0 rows affected (0.00 sec)

mysql> SET @center = null;
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT IF(@center <> center, @num:=1, @num:=@num+1) AS num,
    -> @center:=center AS center,
    -> title
    -> FROM single ORDER BY center;
+------+-----------------+-----------------------------------------+
| num  | center          | title                                   |
+------+-----------------+-----------------------------------------+
|    1 | 与田祐希        | 逃げ水                                  |
|    1 | 堀未央奈        | バレッタ                                |
|    1 | 大園桃子        | 逃げ水                                  |
|    1 | 橋本奈々未      | サヨナラの意味                          |
|    1 | 深川麻衣        | ハルジオンが咲く頃                      |
|    1 | 生田絵梨花      | 何度目の青空か?                        |
|    1 | 生駒里奈        | ぐるぐるカーテン                        |
|    2 | 生駒里奈        | おいでシャンプー                        |
|    3 | 生駒里奈        | 走れ!Bicycle                           |
|    4 | 生駒里奈        | 制服のマネキン                          |
|    5 | 生駒里奈        | 君の名は希望                            |
|    6 | 生駒里奈        | 太陽ノック                              |
|    1 | 白石麻衣        | ガールズルール                          |
|    2 | 白石麻衣        | 今、話したい誰かがいる                  |
|    3 | 白石麻衣        | インフルエンサー                        |
|    4 | 白石麻衣        | シンクロニシティ                        |
|    1 | 西野七瀬        | 気づいたら片想い                        |
|    2 | 西野七瀬        | 夏のFree&Easy                           |
|    3 | 西野七瀬        | 命は美しい                              |
|    4 | 西野七瀬        | 今、話したい誰かがいる                  |
|    5 | 西野七瀬        | インフルエンサー                        |
|    6 | 西野七瀬        | いつかできるから今日できる              |
|    1 | 齋藤飛鳥        | 裸足でSummer                            |
|    2 | 齋藤飛鳥        | いつかできるから今日できる              |
+------+-----------------+-----------------------------------------+
24 rows in set (0.00 sec)

こちらのStackoverflowを参考にしました。

https://ja.stackoverflow.com/questions/11654/mysql%E3%81%AEsql%E3%81%AB%E3%81%A6%E3%82%B0%E3%83%AB%E3%83%BC%E3%83%97%E5%86%85%E3%81%A7%E9%80%A3%E7%95%AA%E3%82%92%E4%BB%98%E3%81%91%E3%81%9F%E3%81%84

これをサブクエリとして応用して次のように書くと縦持ち⇒横持ちへと変換できます。

SELECT single_2.center,
       MAX(CASE single_2.num WHEN 1 THEN single_2.title END) AS cd_1,
       MAX(CASE single_2.num WHEN 2 THEN single_2.title END) AS cd_2,
       MAX(CASE single_2.num WHEN 3 THEN single_2.title END) AS cd_3,
       MAX(CASE single_2.num WHEN 4 THEN single_2.title END) AS cd_4,
       MAX(CASE single_2.num WHEN 5 THEN single_2.title END) AS cd_5,
       MAX(CASE single_2.num WHEN 6 THEN single_2.title END) AS cd_6
FROM
  (SELECT IF(@center <> center, @num:=1, @num:=@num+1) AS num, @center:=center AS center, title
   FROM single
   ORDER BY center) AS single_2
GROUP BY single_2.center;

+-----------------+-----------------------------+-----------------------------------------+--------------------------+-----------------------------------+--------------------------+-----------------------------------------+
| center          | cd_1                        | cd_2                                    | cd_3                     | cd_4                              | cd_5                     | cd_6                                    |
+-----------------+-----------------------------+-----------------------------------------+--------------------------+-----------------------------------+--------------------------+-----------------------------------------+
| 与田祐希        | 逃げ水                      | NULL                                    | NULL                     | NULL                              | NULL                     | NULL                                    |
| 堀未央奈        | バレッタ                    | NULL                                    | NULL                     | NULL                              | NULL                     | NULL                                    |
| 大園桃子        | 逃げ水                      | NULL                                    | NULL                     | NULL                              | NULL                     | NULL                                    |
| 橋本奈々未      | サヨナラの意味              | NULL                                    | NULL                     | NULL                              | NULL                     | NULL                                    |
| 深川麻衣        | ハルジオンが咲く頃          | NULL                                    | NULL                     | NULL                              | NULL                     | NULL                                    |
| 生田絵梨花      | 何度目の青空か?            | NULL                                    | NULL                     | NULL                              | NULL                     | NULL                                    |
| 生駒里奈        | ぐるぐるカーテン            | おいでシャンプー                        | 走れ!Bicycle            | 制服のマネキン                    | 君の名は希望             | 太陽ノック                              |
| 白石麻衣        | ガールズルール              | 今、話したい誰かがいる                  | インフルエンサー         | シンクロニシティ                  | NULL                     | NULL                                    |
| 西野七瀬        | 気づいたら片想い            | 夏のFree&Easy                           | 命は美しい               | 今、話したい誰かがいる            | インフルエンサー         | いつかできるから今日できる              |
| 齋藤飛鳥        | 裸足でSummer                | いつかできるから今日できる              | NULL                     | NULL                              | NULL                     | NULL                                    |
+-----------------+-----------------------------+-----------------------------------------+--------------------------+-----------------------------------+--------------------------+-----------------------------------------+
10 rows in set (0.00 sec)

ウィンドウ関数を使ってないことで本題を見失いそうですが、縦持ちを横持ちに変更するコツはサブクエリの値をCASE句を使って横持ちに変換している点です。

つまり、集計関数はMAXである必要はありませんAVGでもSUMでも良いわけです。

はい、では次は横持ちから縦持ちに変換するパターンを見ていきます。

mysql> SELECT * FROM single_3;
+-----------------+-----------------------------+-----------------------------------------+--------------------------+-----------------------------------+--------------------------+--------------------------------------+
| center          | cd_1                        | cd_2                                    | cd_3                     | cd_4                              | cd_5                     | cd_6                                 |
+-----------------+-----------------------------+-----------------------------------------+--------------------------+-----------------------------------+--------------------------+--------------------------------------+
| 与田祐希        | 逃げ水                      | NULL                                    | NULL                     | NULL                              | NULL                     | NULL                                 |
| 大園桃子        | 逃げ水                      | NULL                                    | NULL                     | NULL                              | NULL                     | NULL                                 |
| 堀未央奈        | バレッタ                    | NULL                                    | NULL                     | NULL                              | NULL                     | NULL                                 |
| 橋本奈々未      | サヨナラの意味              | NULL                                    | NULL                     | NULL                              | NULL                     | NULL                                 |
| 深川麻衣        | ハルジオンが咲く頃          | NULL                                    | NULL                     | NULL                              | NULL                     | NULL                                 |
| 生田絵梨花      | 何度目の青空か?            | NULL                                    | NULL                     | NULL                              | NULL                     | NULL                                 |
| 齋藤飛鳥        | 裸足でSummer                | いつかできるから今日できる              | NULL                     | NULL                              | NULL                     | NULL                                 |
| 白石麻衣        | ガールズルール              | 今、話したい誰かがいる                  | インフルエンサー         | シンクロニシティ                  | NULL                     | NULL                                 |
| 生駒里奈        | ぐるぐるカーテン            | おいでシャンプー                        | 走れ!Bicycle            | 制服のマネキン                    | 君の名は希望             | 太陽ノック                           |
| 西野七瀬        | 気づいたら片想い            | 夏のFree&Easy                           | 命は美しい               | 今、話したい誰かがいる            | インフルエンサー         | つかできるから今日できる             |
+-----------------+-----------------------------+-----------------------------------------+--------------------------+-----------------------------------+--------------------------+--------------------------------------+
10 rows in set (0.00 sec)

まず先に、先程の最終結果と同じ構造の横持ちのデータを準備します。

そして、ここがキモなんですが連番を管理するために一旦pivotテーブルを作ります

mysql> SELECT * FROM cd_num;
+------+
| num  |
+------+
|    1 |
|    2 |
|    3 |
|    4 |
|    5 |
|    6 |
+------+
6 rows in set (0.00 sec)

こういうテーブルです。CROSS JOINつまり直積計算をするためだけにテーブルを作ります。

さてこの発想さえできてしまえばあとは簡単です。

mysql> SELECT center,
    -> CASE num
    -> WHEN 1 THEN single_3.cd_1
    -> WHEN 2 THEN single_3.cd_2
    -> WHEN 3 THEN single_3.cd_3
    -> WHEN 4 THEN single_3.cd_4
    -> WHEN 5 THEN single_3.cd_5
    -> WHEN 6 THEN single_3.cd_6
    -> END AS title
    -> FROM single_3 CROSS JOIN cd_num;

これを実行すると…

+-----------------+-----------------------------------------+
| center          | title                                   |
+-----------------+-----------------------------------------+
| 与田祐希        | 逃げ水                                  |
| 与田祐希        | NULL                                    |
| 与田祐希        | NULL                                    |
| 与田祐希        | NULL                                    |
| 与田祐希        | NULL                                    |
| 与田祐希        | NULL                                    |
| 大園桃子        | 逃げ水                                  |
| 大園桃子        | NULL                                    |
| 大園桃子        | NULL                                    |
| 大園桃子        | NULL                                    |
| 大園桃子        | NULL                                    |
| 大園桃子        | NULL                                    |
| 堀未央奈        | バレッタ                                |
| 堀未央奈        | NULL                                    |
| 堀未央奈        | NULL                                    |
| 堀未央奈        | NULL                                    |
| 堀未央奈        | NULL                                    |
| 堀未央奈        | NULL                                    |
| 橋本奈々未      | サヨナラの意味                          |
| 橋本奈々未      | NULL                                    |
| 橋本奈々未      | NULL                                    |
| 橋本奈々未      | NULL                                    |
| 橋本奈々未      | NULL                                    |
| 橋本奈々未      | NULL                                    |
| 深川麻衣        | ハルジオンが咲く頃                      |
| 深川麻衣        | NULL                                    |
| 深川麻衣        | NULL                                    |
| 深川麻衣        | NULL                                    |
| 深川麻衣        | NULL                                    |
| 深川麻衣        | NULL                                    |
| 生田絵梨花      | 何度目の青空か?                        |
| 生田絵梨花      | NULL                                    |
| 生田絵梨花      | NULL                                    |
| 生田絵梨花      | NULL                                    |
| 生田絵梨花      | NULL                                    |
| 生田絵梨花      | NULL                                    |
| 齋藤飛鳥        | 裸足でSummer                            |
| 齋藤飛鳥        | いつかできるから今日できる              |
| 齋藤飛鳥        | NULL                                    |
| 齋藤飛鳥        | NULL                                    |
| 齋藤飛鳥        | NULL                                    |
| 齋藤飛鳥        | NULL                                    |
| 白石麻衣        | ガールズルール                          |
| 白石麻衣        | 今、話したい誰かがいる                  |
| 白石麻衣        | インフルエンサー                        |
| 白石麻衣        | シンクロニシティ                        |
| 白石麻衣        | NULL                                    |
| 白石麻衣        | NULL                                    |
| 生駒里奈        | ぐるぐるカーテン                        |
| 生駒里奈        | おいでシャンプー                        |
| 生駒里奈        | 走れ!Bicycle                           |
| 生駒里奈        | 制服のマネキン                          |
| 生駒里奈        | 君の名は希望                            |
| 生駒里奈        | 太陽ノック                              |
| 西野七瀬        | 気づいたら片想い                        |
| 西野七瀬        | 夏のFree&Easy                           |
| 西野七瀬        | 命は美しい                              |
| 西野七瀬        | 今、話したい誰かがいる                  |
| 西野七瀬        | インフルエンサー                        |
| 西野七瀬        | つかできるから今日できる                |
+-----------------+-----------------------------------------+
60 rows in set (0.00 sec)

こうなります。

全部を一旦縦持ちにしたはいいけど大抵のケースに置いてNULLは必要ない。

よって、今度はコレ自体をサブクエリにしてNULLのものを消しちゃいます。

mysql> SELECT sub.* FROM (SELECT center,
    -> CASE num
    -> WHEN 1 THEN single_3.cd_1
    -> WHEN 2 THEN single_3.cd_2
    -> WHEN 3 THEN single_3.cd_3
    -> WHEN 4 THEN single_3.cd_4
    -> WHEN 5 THEN single_3.cd_5
    -> WHEN 6 THEN single_3.cd_6
    -> END AS title
    -> FROM single_3 CROSS JOIN cd_num) sub
    -> WHERE sub.title IS NOT NULL;
  
+-----------------+-----------------------------------------+
| center          | title                                   |
+-----------------+-----------------------------------------+
| 与田祐希        | 逃げ水                                  |
| 大園桃子        | 逃げ水                                  |
| 堀未央奈        | バレッタ                                |
| 橋本奈々未      | サヨナラの意味                          |
| 深川麻衣        | ハルジオンが咲く頃                      |
| 生田絵梨花      | 何度目の青空か?                        |
| 齋藤飛鳥        | 裸足でSummer                            |
| 齋藤飛鳥        | いつかできるから今日できる              |
| 白石麻衣        | ガールズルール                          |
| 白石麻衣        | 今、話したい誰かがいる                  |
| 白石麻衣        | インフルエンサー                        |
| 白石麻衣        | シンクロニシティ                        |
| 生駒里奈        | ぐるぐるカーテン                        |
| 生駒里奈        | おいでシャンプー                        |
| 生駒里奈        | 走れ!Bicycle                           |
| 生駒里奈        | 制服のマネキン                          |
| 生駒里奈        | 君の名は希望                            |
| 生駒里奈        | 太陽ノック                              |
| 西野七瀬        | 気づいたら片想い                        |
| 西野七瀬        | 夏のFree&Easy                           |
| 西野七瀬        | 命は美しい                              |
| 西野七瀬        | 今、話したい誰かがいる                  |
| 西野七瀬        | インフルエンサー                        |
| 西野七瀬        | つかできるから今日できる                |
+-----------------+-----------------------------------------+
24 rows in set, 24 warnings (0.00 sec)

完成です。

おわり

今回は「クロス結合とはそもそも何なのか」「具体的にはこんなケースで活用できるよ!」というお話でした。

参考文献

MySQLでテーブル構造の縦横を変換する

結合入門(クロス結合、内部結合、外部結合)

RDBの縦持ちテーブルと横持ちテーブル、およびその変換について · GitHub

dev.classmethod.jp

blog.amedama.jp

crmprogrammer38.hatenablog.com

perlでHashの一部分をテストで確認したいときにsuperhashof便利やん。

f:id:taiga006:20180509225412p:plain:w500
use Test::More;
use Test::Deep;

my $user = {
        name => '齋藤飛鳥',
        age => 19,
        height => 158,
        blood_type => 'O',
        center => '裸足でSummer',
    };

is $user->{age}, 19;
cmp_deeply $user, superhashof { name => '齋藤飛鳥', blood_type => 'O' };

done_testing;

[output]

₍ ᕕ( ‘ω’)ᕗ⁾ $ prove -lvf superhashof.pl
superhashof.pl ..
ok 1
ok 2
1..2
ok
All tests successful.
Files=1, Tests=2,  0 wallclock secs ( 0.03 usr  0.01 sys +  0.07 cusr  0.01 csys =  0.1
2 CPU)
Result: PASS

こける場合はこんな感じ。

use Test::More;
use Test::Deep;

my $user_2 = {
        name => '斉藤優里',
        age => 24,
        height => 157,
        blood_type => 'O',
        center => '13日の金曜日',
    };

cmp_deeply $user_2, superhashof { name => '齋藤優里', height => 157 };

done_testing;

[output]

₍ ᕕ( ‘ω’)ᕗ⁾ $ prove -lvf superhashof.pl
superhashof.pl ..
not ok 1
#   Failed test at superhashof.pl line 12.
# Compared $data->{"name"}
#    got : '斉藤優里'
# expect : '齋藤優里'
1..1
# Looks like you failed 1 test of 1.
Dubious, test returned 1 (wstat 256, 0x100)
Failed 1/1 subtests

Test Summary Report
-------------------
superhashof.pl (Wstat: 256 Tests: 1 Failed: 1)
  Failed test:  1
  Non-zero exit status: 1
Files=1, Tests=1,  0 wallclock secs ( 0.02 usr  0.00 sys +  0.05 cusr  0.01 csys =  0.08 CPU)
Result: FAIL

[参考]

Test::Deep - search.cpan.org

gitのfor-each-refで各ブランチで最後にcommitした人とその更新時刻を一覧表示させる。

普段はあまりそんな状況ないんですがふと今の作業ブランチだけでなくて、すべてのブランチを対象に最新のcommit情報をその更新時刻付きで表示したくなり「うーん、うまいやり方ないかなー」と思ってググったらgit for-each-refが使えるとのこと。知らなかった。

公式ドキュメント

Git - git-for-each-ref Documentation

【例】

git for-each-ref \
--sort=-committerdate \
--count=10 \
--format="
Date: %(color:red)%(authordate:iso)%(color:reset)
%(color:green)[%(authorname)]%(color:reset)
Ref: %(color:yellow)%(refname:short)%(color:reset)
Subject: %(subject)" \
refs/heads refs/remotes

上の例だと

  • 最新のコミット順
  • 10件
  • 日付とブランチ名とユーザ名とcommitメッセージ含め

て表示してくれる。 (色とかつけてるからごちゃごちゃしてるけど、整理すればシンプル。)

for-each-refは単体で使うよりこれを使ってブランチ一覧を取得してその上で何かする、みたいな状況で利用されることが多いらしい。

とはいえ、上の例を参考に上手く使えば
「さっき作業してたブランチなんだっけ?」
とか
「あのブランチって誰がいつ切ったの?」
みたいな調査が楽にできそう。

長いので.gitconfigにaliasを追加しておけば良さそう。

[alias]
    history = for-each-ref --sort=-committerdate --count=10 --format='Date: %(color:red)%(authordate:iso)%(color:reset)\t%(color:green)[%(authorname)]%(color:reset)\nRef: %(color:yellow)%(refname:short)%(color:reset)\nSubject: %(subject)\n' refs/heads refs/remotes

f:id:taiga006:20180504172346p:plain

RedashのRepo.で試しにやってみた図)


...と思ったらすでにこういうのがあるらしい。 まあ、誰かしら作ってるとは思ったけど。

github.com


参考

shuzo-kino.hateblo.jp

kakakakakku.hatenablog.com

「DNSをはじめよう」を読んだ。(技術書典4読書)

先日、秋葉原であった技術書典4で購入した本をこのGWに消化しようとしている。

最初に読んだのが@mochikoAsTech著「DNSをはじめよう」。

f:id:taiga006:20180429162526p:plain:w300

初参加の技術書典で750冊も売れたらしい。すごい。

表紙にもあるように「試しながら学べる」、いわゆるハンズオン形式の200ページもない本である。

具体的に本書で何を試すのかといえば

①お名前.comで好きなドメインを購入

②作ったドメインのネームサーバをAWSのRoute53に変更

whoisやdigを駆使してDNSを詳しく学習

と行った具合である。

スクショ画像が多く、この辺素人の人でもスムーズに手順を終えると思う。

また、本書はハンズオンの合間合間に具体的なシチュエーションが設定されたクイズが差し込まれており「なるほどそういうケースのときのためにこうしておくのか」みたいな学びが多い。

個人的には「ネームサーバ=電話帳」、「フルリゾルバ=秘書」の例えがわかりやすかった。

このおかげでいわゆる名前解決のトラブルってのがどの辺で起きるのか理解できた。

付録のAWSアイドルソング「愛はわがままサンシャイン」は専門用語の多いAWSから初心者には難しいワードをふんだんに盛り込んだ迷曲?そろそろ誰かがボカロに歌わせそう。

ふたりの思い出Redshihftって節が好き。


さて、以下は本書を読んでまだわかってないこと

  • 基本オープンリゾルバをフル活用でよくない?

  • /etc/resolv.cnfはどういうタイミングで書き換わっている?

  • nslookupdigの使い分け(今後はdigだけ使えれば特に困らない?)

  • TTLってどうやって更新するの?

この辺は追って自分で勉強しよう。


参考

mochikoastech.hatenablog.com

mochikoastech.hatenablog.com

技術書典4に行き当たりばったりで参加してきた

技術書典4に参加してきました。

戦利品は以下の通りです。

f:id:taiga006:20180422212822p:plain

  1. DNSをはじめよう ~基礎からトラブルシューティングまで~

  2. WordPressで始めるGoogle Cloud Platform本格入門

  3. radiberry pi! 構築手順書(ver 2.00)

  4. ZIP、完全に理解した

f:id:taiga006:20180422212927p:plain

  1. KbD C93 DECEMBER 2017

  2. もっとわかるVue (Better understanding of Vue in Vuetify)

  3. Firebase + React.js リアルタイムアプリケーション入門

  4. イヌでもわかるhyperapp

  5. たのしいGitオブジェクトの歩き方


(一部、友人のために買った本が含まれています。)

もともと技術書典というイベントについては「名前は聞いたことあるけど…」レベルで、興味はあるものの足を運ぶつもりはありませんでした。ただ今回前日になって「行かない?」と先輩に声をかけてもらったので「おぉ…まじか」となりつつほとんど前情報なく参加することになりました。

 

以下一般参加者として気がついた点をまとめておきます。(後学のため)


1.大きめのトートバックなどを持って参加すべきだった

こういうイベント自体に慣れていないため普段使いのバッグで参加したんですが購入した本の出し入れなどで周りの人に まじで迷惑 だったと思います。ごめんなさい。イベント内で販売していた公式の手提げ袋みたいなのは入口一箇所で販売しており気がついたときには遅かったです。

 

2.後払いシステムが超便利

いやこれ自体は当たり前のことなんですが、思っていた以上に多くのサークルが後払い決済を導入していて朝の東横線並みに混んでてもスムーズに冊子の購入やりとりが可能でした。

 

3. 見えないスタンプがよくわからなかった

お昼頃に行ったんですが想像以上に混んでおり「うげえまじかよ」と一瞬戦意喪失しかけたんですが、運営スタッフの方々の的確な指示のおかげで思っていたより早く整理券GET&会場入りができました。ただ、整理券と一緒に手の甲に押された透明のスタンプは結局なんだったのかが疑問。ああいうイベントではデフォなのかな?

 

4. 次回はもっと大きな会場がいいな(小声)

まだ公式のトータル参加者人数は出ていないようですが一部Twitter情報によると5000人はゆうに超えたとのことで、そうなると次回はもう少しスペースに余裕のある会場が…いいな...なんて思ったり思わなかったり。


それから、これは後学のためでもなんでもないですが、「わざわざ暑い中、秋葉原まで足を運んで技術者が本買うの?笑」みたいなツイートを見て思ったのは(まあ真剣に言ってる人はいないと思いますが)わざわざ足を運んだんだから自分の趣味じゃない本にも手を出してみようかな?みたいな偶然の出会いチックなものが、やはりこういうイベントの醍醐味なんじゃないかな、ということです。

今回で言えばHyperappの本なんて普段サーバーやインフラ周りのことしか見ていない自分が一人で勉強してたら絶対買わなかっただろうと思います。それを、たまたま立ち読みして「ほーん面白そう」ってだけで買えてしまうのがリアルイベントの良さなのかぁ、と改めて思いました。


以下、買いたかったけど買えなかった(買い忘れた)書籍。

『Swiftで書いておぼえるTDD』

『流体計算で覚えるPython3』

『公務員の文書改竄防止システムをブロックチェーンで作ってみた』

『Effective 量子コンピュータ

『趣味のFPGA入門』

電子書籍版とかそのうち出るかな(もしくはもう出てるのかな)


買った本はGWにゆっくり読もう。

表紙ははずいが役に立つ ~良書紹介「雅なPerl」~

「初めてのPerl」の第7版が今年の1月に出ていたらしい。

初めてのPerl 第7版

初めてのPerl 第7版


これこそまさしく「ザ・Perl入門書」ではあるとは思うけど、今日は「雅なPerl」という一風変わった本を紹介したい。

全体で200ページ程度の量で、難しい背景や言語の仕組みに関わる話はすっ飛ばしてPerlを使って如何に書きたいことを書くか、その方法が章立ててまとまっている。 (しかもラノベ調で)

初学者(あるいは基礎がガバガバな半端者=僕)みたいな人が分厚い参考書を手に取る前にサクッと読みながら時々写経してみるのにぴったりな本だと思う。

表紙から溢れ出る同人誌感はさておいて、この本はPerl入学式なんかでも立派な一参考資料として紹介されるくらい、その道の人も認めている本なのだ。

(本当に?)

github.com

ラクダ本やリャマ本と並べて紹介されてるぞ..!?

良い点

  • 雅が初学者目線で常に語ってくれるのでどこまでを一読で理解する必要があってどこからが応用(今後勉強していきましょうねー)な内容なのかがわかりやすい。

  • Perlが得意とする文字列操作、特に正規表現に関する解説が特に充実している。 今でもリファレンスとして時たまペラペラとめくる。

  • 200ページくらいでサイズもコンパクトで持ち運びしやすい。 まあ電子書籍が主流の現代において「重さ」「デカさ」はあまり重要視されないパラメータではありますが...。

悪い点

  • オブジェクト指向の説明に関しては12章まるまる使ってるとはいえPerlで、この短さで、なんとかしようとなるとやっぱり厳しい印象。

  • この表紙だと外出先で開きにくい。うぅ...試されている…。

  • 非売品

近くのPerl Mongerおじさんに持っていないか聞くのが吉。

ちなみに僕が持ってるのは第1版だけど第3版(Perl6の話とか追加)まであるらしい。
第2版の表紙が一番好き。

それから、この本に限ったことではないけどPerl後方互換性が強いので古い参考書でも全然現役で勉強になることがたくさん書いてある。

これが他の言語ではそうはいかない。
先週見たQiitaの記事がすでに過去の遺産だったりする。 きゃー大変。

まあPerlでもあんまり古い本とかサイトをみるよりは公式ドキュメント見ろよ、ってのはもちろん正論なんだけど。

kazhiramatsu.hatenablog.com

書評のようなもの ++ 雅なPerl入門 | koji_magi::*

チームの朝会運営の仕事が怠いのでSlackのBotにしたよ

...まあ1年前の話なんですけど。

github.com

朝会のスピーチ管理がこれまで手動管理だったのをGASで自動化したぞい、というものです。

Google Spreadsheetで発表者のスケジュールとテーマを管理しています。(こんな感じ)

f:id:taiga006:20180415153327j:plain:w600

トリガーをセットして定時にSlackの特定のチャンネルに投稿されるようになってます。

f:id:taiga006:20180415153229j:plain:w500

朝会の運営を新卒の子に引き継ぐに当たって「これ、便利ですね!」って言われて嬉しかったので共有です。

(スピーチスキップとかのときの機能追加する、追加するって言っておいてやってないな...)

日付・時間の文字列操作にはDATE_FORMATよりEXTRACTのほうが便利そう。

チームメンバーの書いたクエリで見覚えのない関数が使われいたので調査。

MySQL :: MySQL 5.6 リファレンスマニュアル :: 12.7 日付および時間関数

EXTRACT関数を使うとDATE値の結果から一部を抽出できる。
よく見るDATE_FORMAT関数を使うより文字列を解釈せずに必要な部分を抽出できるため早いらしい。

mysql> SELECT EXTRACT(HOUR_MINUTE FROM now());
+---------------------------------+
| EXTRACT(HOUR_MINUTE FROM now()) |
+---------------------------------+
|                            2353 |
+---------------------------------+
1 row in set (0.00 sec)

mysql> SELECT EXTRACT(DAY_MINUTE FROM '2012-04-13 21:10:41');
+------------------------------------------------+
| EXTRACT(DAY_MINUTE FROM '2012-04-13 21:10:41') |
+------------------------------------------------+
|                                         132110 |
+------------------------------------------------+
1 row in set (0.00 sec)

グループ化する際に特に便利。

qiita.com

qiita.com

以下、適当なテーブルを作って検証。

mysql> SELECT * FROM user LIMIT 1;
+----+-------+------+------+------------+---------------------+
| id | name  | age  | sex  | city       | created_at          |
+----+-------+------+------+------------+---------------------+
|  1 | illum |   43 | male | Wolffmouth | 2007-12-30 07:13:59 |
+----+-------+------+------+------------+---------------------+
1 row in set (0.00 sec)

mysql> SELECT sex,
       EXTRACT(YEAR
               FROM created_at) AS YEAR,
       COUNT(*) AS COUNT
       FROM USER
       GROUP BY sex,
         EXTRACT(YEAR
                 FROM created_at) HAVING COUNT(*) > 10
       ORDER BY extract(YEAR
                 FROM created_at);
+--------+------+-------+
| sex    | YEAR | COUNT |
+--------+------+-------+
| female | 1977 |    14 |
| male   | 1984 |    14 |
| female | 1984 |    13 |
| male   | 1990 |    11 |
| female | 1991 |    11 |
| female | 1998 |    11 |
| female | 2006 |    13 |
| male   | 2006 |    11 |
| male   | 2011 |    16 |
+--------+------+-------+
9 rows in set (0.00 sec)

最後にEXTRACTで使えるunit値を載せておく。

unit 要求される expr 書式
MICROSECOND MICROSECONDS
SECOND SECONDS
MINUTE MINUTES
HOUR HOURS
DAY DAYS
WEEK WEEKS
MONTH MONTHS
QUARTER QUARTERS
YEAR YEARS
SECOND_MICROSECOND 'SECONDS.MICROSECONDS'
MINUTE_MICROSECOND 'MINUTES:SECONDS.MICROSECONDS'
MINUTE_SECOND 'MINUTES:SECONDS'
HOUR_MICROSECOND 'HOURS:MINUTES:SECONDS.MICROSECONDS'
HOUR_SECOND 'HOURS:MINUTES:SECONDS'
HOUR_MINUTE 'HOURS:MINUTES'
DAY_MICROSECOND 'DAYS HOURS:MINUTES:SECONDS.MICROSECONDS'
DAY_SECOND 'DAYS HOURS:MINUTES:SECONDS'
DAY_MINUTE 'DAYS HOURS:MINUTES'
DAY_HOUR 'DAYS HOURS'
YEAR_MONTH 'YEARS-MONTHS'

Test::Mock::Guard ~テスト用にお手軽にstub化~

今日も今日とて、これまでなんとなくで使ってたモジュールを再度見つめ直す回です。

github.com

Test::Mock::Guardはテストで使えるモジュールとしてメジャーな模様。既存のクラス挙動を簡単にオーバーライドできる。

use strict;
use warnings;
use Test::More;
use Test::Mock::Guard qw/ mock_guard /;

package Discord;

sub new { bless {} => shift; }
sub solo { "長濱ねる"; }

package main;

{
    my $guard = mock_guard "Discord", +{
            solo    => sub { "平手友梨奈"; },
        };

    my $song0 = Discord->new;
    is $song0->solo, "平手友梨奈", "mock化されてる";
}

print "------(OUT OF SCOPE)--------\n";
my $song = Discord->new;
is $song->solo, "長濱ねる", "mock化されない";

done_testing;
〓 ~/perl_study
₍ ᕕ( ‘ω’)ᕗ⁾ $ prove -lvf discord.t
discord.t ..
ok 1 - mock化されてる
------(OUT OF SCOPE)--------
ok 2 - mock化されない

1..2
ok
All tests successful.
Files=1, Tests=2,  0 wallclock secs ( 0.02 usr  0.00 sys +  0.06 cusr  0.01 csys =  0.09 CPU)
Result: PASS

無駄にネストが深くならずに済む。

よく聞くスタブとモックの違いについて。

厳密に正しいかはあれですが、この記事が参考になりました。

perl-users.jp

スタブの場合は、それを利用する部分がテスト対象になります。

( 中略)

一方、モックの場合は、適用する部分そのものがテスト対象です。

( 中略)

ですので、今テストしたい部分がどこかを的確に認識できれば、 モックとスタブのどちらを使うのがよい状況なのかを判断できるようになります。

ちなみに最近よく聞く?Test2にもメソッドをモックしてくれる君としてTest2::Mockというのがあるみたいなんですがこいつだとモックしたメソッドを何回呼ばれたかを知るcall_count同等の機能がない様子。

techblog.kayac.com

Test2についてはまた記事を書きたいと思います。

参考記事

mihyaeru21.hatenablog.com

blog.yuuk.io

d.hatena.ne.jp