JUST FOR FUN

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

sprintf関数で自由自在に数字や文字列のフォーマットを指定する

1234 -> 001234 みたいな数字のゼロ埋め作業をPerlで楽にやる方法。

下記のように書くと便利です。

my $hoge = 1234;
my $fuga = sprintf("%06d", $hoge);
print $fuga;
# -> 001234

sprintf関数は指定した書式で文字列を作成することが出来ます。

応用して小数点の丸め込み(四捨五入)にも使えます。

my $hoge = 12.343;
my $fuga = sprintf("%.2f", $hoge);
print $fuga;
# -> 12.35

0をなくせばspace埋めも可能です。

$fuga = sprintf("%-6s", 1234);
# -> '1234  '
$fuga = sprintf("%6s", 1234);
# -> '  1234'

浮動小数点数や16進数との返還などもsprintf関数でたやすくできます。

d.hatena.ne.jp

d.hatena.ne.jp

"First Things to Know about TouchDesigner"(抄訳) Part5

前回の続きです。

チュートリアル動画を見て学んだTouchDesignerの基本的な部分を抄訳としてまとめています。

vimeo.com

今回がラストです。 おつきあいいただきありがとうございました。


27. DATs are Powerful Text-manipulation Operators

- DAT = "Data Operator" = TD内のテキストを保存および操作する
- テキストDATはイベント駆動で実行できるスクリプトとして使える
- Web DAT... HTMLを容易に取得できる、ただし、ASCII形式のテキストデータ(like Glsl Shaders or scripts)としてに限る
- Monitors DAT ... テキストを含む行と列を持ったテーブル

28. Sweet Sixteen Operators

- TD内でよく使う16個のOperator群をそう呼ぶらしい

29. Explore the Operator Snippets

- Help -> Operator Snippetsから各Operatorの簡単な使用例を見ることができる

30. Get Components from the Palette

- 最初に消したPaletteブラウザには最近起動したネットワークであったりカスタマイズされたコントロールパネルが表示される
- つまり作成したComponentをここに保存しておいて他のプロジェクトから簡単に呼び出すこともできる
- UI/gal には20個のカスタマイズ済みのガジェットがあり、これをコピペするだけでコントロールパネルを作成することもできる

f:id:taiga006:20180729205325p:plain ※ UI/gal の中身

Norway Workshop Videos | Creative Projection Week 2016
※ ここにある"A Movie Player Panel and Building UIs"というチュートリアル動画でコントロールパネルの組み立て方の基礎が学べる

31. Get Components from the .tox Forum

- TDのメニューバーにある[ EXAMPLES ]から.toxコンポーネントフォーラム(www.derivative.ca/forum)に飛べる
- ここで.toxファイルをクリックすると新しいTDセッションが展開されてる
- あるいはDLすることもできるし、TDにドラッグ&ドロップで持ってくることもできる

32. Speeding it Up with the Performance Monitor

- [Dialogs -> Performance Monitor]で1つのフレームでどのNodeがどの順番でどれくらい時間をかけて実行されたか確認できる(on the CPU not the GPU)
- Perform CHOPやinfo CHOPを使って色々なパラメータを調べることもできる

33. Quick Tips and Good Habits

- Color Code Nodes ... ネットワーク上で"c"を押すと色見本が展開される、色を選択することでNodeの外観を変えることができる(当然複数のものをまとめて行うこともできる)

- network overview ... ネットワーク上で"o"を押すとノードマップが出る

- Shiftを押しながらNodeを作るとOP Createを閉じることなくNodeを連続で作成できる

- Nodeの名前は大文字と小文字を区別する

- Nullを噛ませることで、例えば別の場所で参照されるオペレータに直接、別のオペレータを影響させることなく編集できる

- トラブルシューティングには Info DAT, Info CHOPを活用する

33は簡単なところは少し省略しました。

以上です。

"First Things to Know about TouchDesigner"(抄訳) Part4

前回の続きです。

チュートリアル動画を見て学んだTouchDesignerの基本的な部分を抄訳としてまとめています。

vimeo.com

後半動画も、中盤。残りわずか。


23. A Path is an address of a Node

- PathはNodeあるいはOperatorのアドレス(位置)のようなもの
- 多くのOperatorは他のOperatorを参照するためのPathパラメータを持つ
- 親となるNodeを参照する場合【Python Expression】では parent() を使う

f:id:taiga006:20180729200006p:plain ※ info CHOPのOperator parameterに絶対パスで得たい情報を入れた(ここでも勝手に接続される)

24. Render a 3D Scene with a Render TOP

- Render TOPを使って3Dオブジェクトをレンダリングする
- そのためにはGeometry, Light, Camera 3つのComponentsが必要
- それらを作ると勝手にRender TOPに点線で接続される (つまり参照している)

f:id:taiga006:20180729195929p:plain

25. Timeline lets you Play, Pause and Examine

- 左下に表示されるFPSはTouchDesigner内の1秒間のフレーム数(設定値)
- 上に表示されるFPSは直前に描画された1秒間のフレーム数(実測値)
- TouchDesignerは主にfree-runningクロックでイベントドリブンなのでタイムラインとそのFlフレーム番号を使うことは滅多にない

※ Movie File In TOPは基本的にはタイムラインのフレーム番号などには同期しないが、Play Modeメニューから"Locked to Timeline"を選択すると動画とタイムラインのフレーム番号が同期される。

26. Create Animation Curves with the Animation Editor

- Animation作成にはAnimation COMPが使える
- Animation COMPはデフォルトではチャンネル出力を持たない
- Animation COMPを右クリック[Edit Animation...]を選択するとEditorが展開される
- [Add Channels]で3チャンネル(tx, ty, tz)が作成
- キーフレームはEditor上ではドットで表示される
- キーフレームを追加するにはalt + 左クリック
- ドットではなくカーブ自体を選択してメニューから関数を変更することができる
ex) cubic(), linear(), ease(), raw(), constant() ...

f:id:taiga006:20180729200232p:plain ※ (tx,ty,tz)を色々いじってみた。


次回が最後かな。

"First Things to Know about TouchDesigner"(抄訳) Part3

前回の続きです。

チュートリアル動画を見て学んだTouchDesignerの基本的な部分を抄訳としてまとめています。

vimeo.com

ちょうど前回のPart2までで動画の前編部分が終わりました。今回から後編です。


18. Parameters and the three "Parameter Modes"

- TouchDesignerの一般的なパラメータは以下の7つ
- 整数 (interger)
- 浮動小数点 (floating point number)
- ON-OFF
- メニュー
- 文字列(text string)
- 別のNodeへのパス
- オペレータに一度だけ何かをさせるためのパルス

- パラメータ値の動かし方[Parameter Modes]
①【Constant】スライダーを直接操作、あるいは直接数値を入力、メニューから直接何かを選択
②【Expression Mode】pythonの形式で書ける
③【Export Mode】外部(CHOP)から入力された数値によって駆動される

19. CHOPs output Channels of Samples

- CHOPは数値を出力する
- CHOP (Channel Operator)は1つ以上のチャンネルの組み合わせで、それぞれのチャンネルが一連の数値の配列(Sample)である

- Constant
定数。1つのチャンネルに1つのサンプルを持つ。chan1の下にchan2をつくあれば2つのチャンネルを出力することになる。

- Noise 
1つのチャンネルに複数のサンプルを持つ。
Parameter DialogのChannelからChannel Namesを「chan[1-3]」に変更すると3つのチャンネル出力になる。これでトータル600のサンプルを持つ。

f:id:taiga006:20180729004118p:plain
※ Noise CHOPをズームして[Dot Per Sample]したときのもの

f:id:taiga006:20180729004206p:plain
※ 600個のサンプルを持つことが確認できる(600iのiはサンプル数あるいはインデックスを意味する)

- CHOPを数値として扱うには"CHOP to"DATを立ち上げ"Include Names"をONにする
- "Noise"CHOPをそのDATの上にドラッグ&ドロップ
- これで"Noise"CHOPと"CHOP to"DATが接続される

f:id:taiga006:20180729004604p:plain ※ "CHOP to" DATのテーブルに表示される各セルがSampleである

- CHOPはTouchDesigner場では主に曲線や動き、音声信号、あるいは制御信号として使われる

20. Export CHOP Channels to Parameters

-Exportを使えばCHOPチャンネルから他のオペレータのパラメータを変更できる
Movie File In TOPとTransform TOPをつなぐ。  
LFO CHOPからMath CHOPを経由して動的なパラメータをTransform TOPのTranslate (X)にドラッグ&ドロップ(此ときMath CHOPはViewer Acitveモード)する。
表示されるEXport方法の中から"Export CHOP"を選択。

さらにMath CHOPのMult-Addページからパラメータのレンジを決めることもできる。
Math CHOPの右下の緑のドットをOFFにすればExportは一時的にOFFにすることが可能である。

f:id:taiga006:20180729004629p:plain

※ 左右に動くバナナが表現できる。

21. Put a Python Expression in a Parameter

- Pythonはパラメータの中やスクリプト中に使うことができる。 (以前はTscriptも使えた?)

f:id:taiga006:20180729004716p:plain

-  青いボックスがpythonモード、灰色のボックスはデフォルトのConstantモード、緑のボックスはExportモード。

f:id:taiga006:20180729004732p:plain
pythonモードだと変数を選択してカーソルを合わせると数値が表示される。

22. Create a Component with an Input, Output and a Network of Operators

- Operatorの集合体をComponentsと呼ぶ
- CHOP入力でTOP出力にカスタマイズされたComponentを作ってみる

f:id:taiga006:20180729004812p:plain 空のContainer COMPの中にRamp TOPとそれにつなげたOUT TOP,それから In CHOPを作る。 f:id:taiga006:20180729004827p:plain Container COMPの外からBeat CHOPを入力(Null TOPを出力)。
In CHOPに入るそのパラメータをRamp TOPのPhaseパラメータにExportする。

お疲れ様です。

次回へ続く。

"First Things to Know about TouchDesigner"(抄訳) Part2

前回の続きです。

チュートリアル動画を見て学んだTouchDesignerの基本的な部分を抄訳としてまとめています。

vimeo.com


12. Value Ladders help you change Parameter values

- 各パラメータの名前もしくは値の上で左クリック長押しすると[.001 .01 .1 1 10.]の4項目のポップが出てくる
- これはパラメータの増減の単位を意味する
- 複数パラメータを持つ場合は単独でも複数同時でも増減させることができる

13. Navigate into Component Operators that contain Networks

- 灰色のボーダー線を持つNodeは「Components」と呼ばれる
- Componentsの中に入るには対象のNodeを選択して [Enter] あるいは [i]
- Componentsから出るには [u]
- Componentsをズームするともっと楽に中に入れる(逆も然り)

14. Save your work

- Ctrl + sでProjectを保存
- 名前がインクリメントして増幅するが大元を起こせば一番最新の番号のファイルが展開される

15. Get Media into TouchDesigner

- 様々なファイル形式をimportできる
- TouchDesignerのコンポーネントファイル形式 [.tox] もimportできる
- [.toe] 形式のファイルはプロジェクト全体を含むTouchDesignerの環境を持つファイルである
- つまり [.toe] 形式のファイルはimportできない

16. Split Panes and fill with other Pane Types

- 右上の隅にあるプルダウンのメニューからPane分割が可能
- Paneの右上の「▼」メニューから様々なPaneの種類が選べる
- Network Editor (いつも作業している画面)
- Panel (パネルコンポーネントの操作ができる画面)
- Geometry Viewer (3Dシーンやオブジェクトを操作できる)
- Node上で右クリックから[Viewer]を選んでもGeometry Viewer同様のウィンドウが表示される

f:id:taiga006:20180728183135p:plain

17. Operator Flags affect their function and appearance

- Nodeを囲んでいる部分を[Operator Flags]と呼ぶ
- 左側のFlagsは全てのOperator群で固定 
- 下側のFlagsは各Familiesで固定

f:id:taiga006:20180728183214p:plain ※上から [Viewer], [Clone Immute], [Bypass], [Lock]

Part 3へ続く。

"First Things to Know about TouchDesigner"(抄訳) Part1

最近、ちょっと遊びで勉強し始めたTouchDesigner

あまり日本語のドキュメント?的なものはないけど公式のチュートリアルWIKIがすごく充実している。

今回は以下の動画を見て学んだことを抄訳としてまとめておく。

vimeo.com


1. Starting TouchDesigner

- TouchDesignerを始めるにあたって少なくとも3-buttonの機能を持つマウスが必要

2. Pan, zoom and center the Network

- "h"を押すとNetworkが中央揃え(ホーミング)
- 選択中のノードのみをホーミングするには"Shift + h"
- 右クリックのメニューから「Home All」を選択しても同様にホーミング可能

3. Select and move Nodes

- Nodeを右クリックするとNodes メニューが表示
- "View"を選択するとフローティングウィンドウが展開

4. TouchDesigner Operators are Generators or Filters

- Ctrl + A & Deleteで全てのNodeを削除
- 何もない部分をダブルクリックするとOP Create Dialogが表示
- OPは"Operator",あるいは"Node" 
- Tabを押すと同じDialogが表示される

"Movie File Inを設置してさらにそれを"Level"と接続 f:id:taiga006:20180724231445p:plain

5. In the Network Editor, add an Operator

- 6つのOperator Families
- CHOP(Channel Operator)
- 暗い色のOPは「ジェネレータ」、これは新しいデータを作成したり外部デバイスあるいはプログラムからデータを読み込んだりする。明るい色のOPはデータを変更する「フィルタ」

CHOPの"Pattern"をさらに"Noise"作成 f:id:taiga006:20180724231540p:plain

6. Six Families of Operators act on images, motion, 3D and text

- TCP(Texture Operator)⇨画像に対する操作
- CHOP(Channel Operator)⇨信号あるいは音声をコントロール操作
- SOP(Surface Operator)⇨ポリゴン、3D線などのSurface操作
- MAT(Material Operator)⇨3Dオブジェクトにテクスチャやシェーディングを追加

Sphere SOP,Phong MATを選択 f:id:taiga006:20180724231633p:plain

- COMP(Component)⇨3つのコンポーネントのカテゴリが存在
- Geometry COMPはSOPと3Dレンダリング用のマテリアルを備えている
- Slider COMPはコントロールパネルを構築するための2Dガジェットの一つ

Geometry COMP,Slider COMPを選択 f:id:taiga006:20180724231726p:plain

DAT(Data Operator)⇨テーブル構造あるいはもっと自由なテキストデータを操作

Monitors DATを選択 f:id:taiga006:20180724231809p:plain

7. Connect Nodes together with Wires

- Nodeは基本的に左が入力、右が出力
- すでに接続されているNode間に新しいNodeを挿入するには左のNodeの出力部分を右クリック
- あるいはワイヤを右クリックしてメニューから「Insert Operator」

f:id:taiga006:20180724231936p:plain

8. Wires, Data Flow and Cooking

- パラメータを動的に変化させている最中、ワイヤにアニメーションがつく
- これはデータが流れていることを意味する
- 上流のNodeで処理(cooking)されそれが接続先のNodeに送られている

※このCookingの回数?はNodeのinformationで確認できる f:id:taiga006:20180724232222p:plain

GeometryやCamera, Lightのような3Dコンポーネントは上下にコネクタを持つがこれらは3D階層の親子関係を設けるためのものでデータは流れない
- 同様にSlider,Button,Containerのような2Dコンポーネントも上下にコネクタを持つがあくまで複数のコンポーネントを1つのパネルのようにグループ化させることはあってもデータは流れない
- 左右のコネクタで繋がれたワイヤにしかデータは流れない

9. Current Node and Selected Nodes

- 現在のNodeは緑の枠で囲われて選択中のNodeは黄色の枠で囲われる
- Nodeの一番左上にあるFlagをクリックするとNodeのViewが3文字のアイコンに変化する

f:id:taiga006:20180724232419p:plain

10. Make a Viewer Active to Inspect Operator Data

- Alt + 右クリックでNodeのinformationが表示
- Nodeの右下にある"Viewer Active"をONにするとNodeのデータの中身が詳細に見れる
- Panelの場合はPnanelを操作できる

- それ以外にも"Viewer Active"をONにする方法が3つ

①"Alt + a" (一時的に全てのNodeに対して)
②"Shift + a" (全てのNodeに対して)
③"a" (選択中のNodeに対して)

f:id:taiga006:20180724232545p:plain

  1. Adjust Parameters of Operators
- Parameter Dialogは"p"で展開、あるいは閉じることができる
- Nodeを複数選択した状態でParameterを変化させると同期する
- 右クリックで[Reset All Parameters]することで全て初期値に戻る
- Parameter Dialogの[i]を右クリックしても同じようにできる

Part 2へ続く。

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

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

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

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

 

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

 

「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