LoginSignup
0
0

More than 1 year has passed since last update.

Spark SQL - join の挙動について

Last updated at Posted at 2021-07-04

Spark SQL の join はいくつか方法があって、それぞれちょっとずつ挙動が違う。

下記のような DataFrame を2つあったとして

val lowerCase = Seq(
  "a",
  "b",
  "c"
).toDF("lower_case")

val upperCaseMap = Seq(
  ("a", "A"),
  ("b", "B"),
  ("c", "C")
).toDF("lower_case", "lower_case")

=== を使うパターン

lowerCase.join(upperCaseMap, lowerCase("lower_case") === upperCaseMap("lower_case"))

+----------+----------+----------+
|lower_case|lower_case|upper_case|
+----------+----------+----------+
|         a|         a|         A|
|         b|         b|         B|
|         c|         c|         C|
+----------+----------+----------+

それぞれの DataFrame から結合条件に指定した Column を含めて新しく DataFrame を作成する。
重複が嫌な場合は drop(Column) でカラムを削ってしまうのが良さそう。

lowerCase
  .join(upperCaseMap, lowerCase("lower_case") === upperCaseMap("lower_case"))
  .drop(upperCaseMap("lower_case"))

+----------+----------+
|lower_case|upper_case|
+----------+----------+
|         a|         A|
|         b|         B|
|         c|         C|
+----------+----------+

Seq(...) を使うパターン

lowerCase.join(upperCaseMap, Seq("lower_case"))

+----------+----------+
|lower_case|upper_case|
+----------+----------+
|         a|         A|
|         b|         B|
|         c|         C|
+----------+----------+

この場合は Column がマージされる。

結合するときに null も考慮したいとき

前段で紹介した2パターンは null 同士の結合を無視する。

null を含む DataFrame。

val lowerCase = Seq(
  "a",
  "b",
  null
).toDF("lower_case")

val upperCaseMap = Seq(
  ("a", "A"),
  ("b", "B"),
  (null, "Null")
).toDF("lower_case", "upper_case")

=== を使ったとき。null の結合は無視される。

lowerCase.join(upperCaseMap, lowerCase("lower_case") === upperCaseMap("lower_case"))

+----------+----------+----------+
|lower_case|lower_case|upper_case|
+----------+----------+----------+
|         a|         a|         A|
|         b|         b|         B|
+----------+----------+----------+

Seq(...) を使ったとき、null の結合は無視される。

lowerCase.join(upperCaseMap, Seq("lower_case"))

+----------+----------+
|lower_case|upper_case|
+----------+----------+
|         a|         A|
|         b|         B|
+----------+----------+

null の結合をしたい場合は <=>.eqNullSafe(...) を使う

<=> を使ったとき、null の結合ができる。

lowerCase.join(upperCaseMap, lowerCase("lower_case") <=> upperCaseMap("lower_case"))

+----------+----------+----------+
|lower_case|lower_case|upper_case|
+----------+----------+----------+
|         a|         a|         A|
|         b|         b|         B|
|      null|      null|      Null|
+----------+----------+----------+

.eqNullSafe(...) を使っても、null の結合ができる。

lowerCase.join(upperCaseMap, lowerCase("lower_case").eqNullSafe(upperCaseMap("lower_case")))

+----------+----------+----------+
|lower_case|lower_case|upper_case|
+----------+----------+----------+
|         a|         a|         A|
|         b|         b|         B|
|      null|      null|      Null|
+----------+----------+----------+

その他

外部結合したいとき

第三引数に形式を指定する。デフォルトは inner

lowerCase.join(upperCaseMap, lowerCase("lower_case") <=> upperCaseMap("lower_case"), "left")
結合条件を複数指定したいとき

Seq(...) の場合は必要な分だけ column 名を含めればOK。
他は条件を && で繋げばOK。

おわり

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0