join

[Join@Splunk>docs](https://docs.splunk.com/Documentation/Splunk/latest/SearchReference/Join)

LEFT やら OUTERが出てくるので
cf. [SQL素人でも分かるテーブル結合(inner joinとouter join)](https://qiita.com/naoki_mochizuki/items/3fda1ad6594c11d7b43c)

#説明
`join`コマンドを使用して、サブ検索の結果をメイン検索の結果と結合します。 1つ以上のフィールドは、各結果セットに共通でなければなりません。 `selfjoin`コマンドを使用して、検索結果セットをそれ自体に結合することもできます。
#記述方法
```
join [join-options...] [field-list] subsearch
```
#オプション引数
##field-list
なにも書かないと全部のフィールドが一致する必要がある。なお、ケースセンシティブ。
##join-options
###type=(inner | outer | left) 
参考先で十分だと思いつつ、Splunkでやってみる。

```perl:dogs.tbl
| makeresults 
| eval _raw="id	name	owner_id
1	aka	1
2	ao	2
3	shiro	1
4	kuro	4"
| multikv forceheader=1
| table id name owner_id
```

```perl:owner.tbl
|makeresults
|eval _raw="id	name
1	ichiro
2	jiro
3	saburo"
| multikv forceheader=1
| table id name
```
####内部結合
```perl:inner_join.spl
| makeresults 
| eval _raw="id,name,owner_id
1,aka,1
2,ao,2
3,shiro,1
4,kuro,4" 
| multikv forceheader=1 
| table id name owner_id 
| join type=inner left=L right=R where L.id = R.id 
    [|makeresults
    | eval _raw="id,name
1,ichiro
2,jiro
3,saburo" 
    | multikv forceheader=1 
    | table id name]
```

| L.id | L.name | L.owner_id | R.id | R.name |
|--:|:--|--:|--:|:--|
| 1 | aka | 1 | 1 | ichiro |
| 2 | ao | 2 | 2 | jiro |
| 3 | shiro | 1 | 3 | saburo |

####外部結合
```perl:left_outer_join.spl
| makeresults 
| eval _raw="id,name,owner_id
1,aka,1
2,ao,2
3,shiro,1
4,kuro,4" 
| multikv forceheader=1 
| table id name owner_id 
| join type=outer left=L right=R where L.id = R.id 
    [|makeresults
    | eval _raw="id,name
1,ichiro
2,jiro
3,saburo" 
    | multikv forceheader=1 
    | table id name]
```

| L.id | L.name | L.owner_id | R.id | R.name |
|--:|:--|--:|--:|:--|
|1	|aka	|1	|1	|ichiro
|2	|ao	|2	|2	|jiro
|3	|shiro	|1	|3	|saburo
|4	|kuro	|4	| 	| 

なぜかドキュメントに乗っていない`left` `right`と`where`
なおワンセットかつ左右の順番で`where`は書かないといけない。

動作自体は[参照先](https://qiita.com/naoki_mochizuki/items/3fda1ad6594c11d7b43c)と同様、なお、外部参照は左のみ

世の中には[完全外部結合](https://wa3.i-3-i.info/word15313.html)があるけど、Splunkにはない。
やろうとするなら`append`して`stats`でまとめると思います。
##usetime=\<bool>とearlier=\<bool>
結合するサブサーチ結果時間によって制限するオプション
あんまり使用例をみたことがないので見つけ次第描きたいと思います。
##overwrite=\<bool> 
```perl:overwrite_t.spl
| makeresults 
| eval _raw="id,name,owner_id
1,aka,1
2,ao,2
3,shiro,1
4,kuro,4" 
| multikv forceheader=1 
| table id name owner_id 
| join type=inner overwrite=t id 
    [|makeresults
    | eval _raw="id,name
1,ichiro
2,jiro
3,saburo" 
    | multikv forceheader=1 
    | table id name]
```
の結果が
1. overwrite=true

| id | name | owner_id |
|:--|:--|:--|
| 1 | ichiro | 1 |
| 2 | jiro | 2 |
| 3 | saburo | 1 |
2. overwite=false

| id | name | owner_id |
|:--|:--|:--|
| 1 | aka | 1 |
| 2 | ao | 2 |
| 3 | shiro | 1 |
となる。
サブサーチでフィールドの存在だけが必要でメインサーチに影響を与えない場合に使えるかも
##max=\<int>
基本は`1`なので一つだけ結合するが、結合する数を変更することができる

```perl:outer_join_with_max.spl
| makeresults 
| eval _raw="id,name,owner_id
1,aka,1
2,ao,2
3,shiro,1
4,kuro,4" 
| multikv forceheader=1 
| table id name owner_id 
| join left=L right=R type=outer overwrite=t max=0 where L.owner_id = R.id 
    [|makeresults
    | eval _raw="id,name
1,ichiro
2,jiro
3,saburo" 
    | multikv forceheader=1 
    | table id name]
```

| L.id | L.name | L.owner_id | R.id | R.name |
|--:|:--|--:|--:|:--|
| 1 | aka | 1 | 1 | ichiro |
| 2 | ao | 2 | 2 | jiro |
| 3 | shiro | 1 | 1 | ichiro |
| 4 | kuro | 4 |   |   |
と重複して結合ができる。
初めてやったが、`where`での結合便利:smile:

なお、

```perl:where_nest.spl
| join left=L right=R type=left overwrite=t max=0 where L.owner_id = R.id L.id = R.id
```
なこともできる。

| L.id | L.name | L.owner_id | R.id | R.name |
|--:|:--|--:|--:|:--|
| 1 | aka | 1 | 1 | ichiro |
| 2 | ao | 2 | 2 | jiro |
| 3 | shiro | 1 |   |   |
| 4 | kuro | 4 |   |   |

#まとめ
Splunkを始めたころはよくお世話になる`join`
２回検索することになるので、慣れてくると出来るだけ使わないように頑張ることになります。
個人的には、`join`を使わないクエリーを書けるようになるのと上達したかな〜と思いました。:sweat:
ただし、サブサーチ側がCSVだったり検索時間がかからないものだと、わかりやすいしオプションを使って簡単にテーブルから結果を出せるので使いどころですね。