10
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

BigQueryのMERGEステートメントの検証

Last updated at Posted at 2020-09-24

BigQueryのMERGEステートメントはINSERTとUPDATEを同時にできるが、その使い方を理解するために検証してみました。

次の2つのテーブルがあったとします。

#####source_tbl

id name price update_date
001 apple 150 2020/8/4
002 orange 150 2020/8/2
003 carrot 50 2020/8/2
004 cabbage 100 2020/8/3
005 pork 300 2020/8/3

#####target_tbl

id name price update_date
001 apple 100 2020/8/1
002 orange 150 2020/8/2
003 carrot 50 2020/8/2
  • source_tblが更新元テーブル
  • target_tblが更新先テーブル
  • source_tblとtarget_tblを比較し、source_tblに更新が発生したレコードはtarget_tblへ反映する
  • その際、update_dateカラムはSQL実行日に設定する
  • SQL実行日は 2020/8/5 とする

##特に条件は指定せず、MERGEをやってみる

MERGE
    target_tbl t
USING
    source_tbl s
ON
    t.id = s.id
WHEN MATCHED THEN
    UPDATE SET
        t.name = s.name
      , t.price = s.price
      , t.update_date = CURRENT_DATETIME('Asia/Tokyo')
WHEN NOT MATCHED THEN
    INSERT
    (
        id
      , name
      , price
      , update_date
    )
    VALUES
    (
        s.id
      , s.name
      , s.price
      , CURRENT_DATETIME('Asia/Tokyo')
    )

###実行結果
#####target_tbl

id name price update_date
001 apple 150 2020/8/5
002 orange 150 2020/8/5
003 carrot 50 2020/8/5
004 cabbage 100 2020/8/5
005 pork 300 2020/8/5

全てのレコードが更新されてしまった。

##EXCEPT DISTINCT句を使用し、変更のあったレコードのみ抽出し、それをソーステーブルとしてMERGEしてみる

MERGE
    target_tbl t
USING
(
    SELECT
        id
      , name
      , price
      , update_date
    FROM source_tbl
    EXCEPT DISTINCT
    SELECT
        id
      , name
      , price
      , update_date
    FROM target_tbl
) s
ON
    t.id = s.id
WHEN MATCHED THEN
    UPDATE SET
        t.name = s.name
      , t.price = s.price
      , t.update_date = CURRENT_DATETIME('Asia/Tokyo')
WHEN NOT MATCHED THEN
    INSERT
    (
        id
      , name
      , price
      , update_date
    )
    VALUES
    (
        id
      , name
      , price
      , CURRENT_DATETIME('Asia/Tokyo')
    )

###実行結果
#####target_tbl

id name price update_date
001 apple 150 2020/8/5
002 orange 150 2020/8/2
003 carrot 50 2020/8/2
004 cabbage 100 2020/8/5
005 pork 300 2020/8/5

変更があったレコードのみ更新・挿入されている。

##仮に、更新があったレコードは必ずupdate_dateカラムが更新される という前提があった場合、EXCEPT DISTINCT句を使用せず、WHEN MATCHED THENにその条件を追加してMERGE

MERGE
    target_tbl t
USING
    source_tbl s
ON
    t.id = s.id
WHEN MATCHED AND s.update_date != t.update_date THEN
    UPDATE SET
        t.name = s.name
      , t.price = s.price
      , t.update_date = CURRENT_DATETIME('Asia/Tokyo')
WHEN NOT MATCHED THEN
    INSERT
    (
        id
      , name
      , price
      , update_date
    )
    VALUES
    (
        id
      , name
      , price
      , CURRENT_DATETIME('Asia/Tokyo')
    )

###実行結果
#####target_tbl

id name price update_date
001 apple 150 2020/8/5
002 orange 150 2020/8/2
003 carrot 50 2020/8/2
004 cabbage 100 2020/8/5
005 pork 300 2020/8/5

変更があったレコードのみ更新・挿入されている。
このやり方のほうがシンプル。
ただ、このやり方だとupdate_dateカラム以外が更新され、update_dateカラムは更新されない場合はそのレコードは変更なしと見做され、更新されない。

10
6
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
10
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?