1
1

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 1 year has passed since last update.

BigQueryで値の補完をする

Last updated at Posted at 2023-03-13

次のようなテーブルがあるとします。

id name flag pre producer
1 ミカン on XXX県産 Aさん
2 ミカン 不明 Aさん
3 リンゴ off 不明 Cさん
4 リンゴ YYY県産 Bさん
5 バナナ 不明 Cさん

以下のような形になるよう整形していきます。

id name flag pre producer
1 ミカン on XXX県産 Aさん
2 ミカン on XXX県産 Aさん
3 リンゴ off YYY県産 Cさん
4 リンゴ off YYY県産 Bさん
5 バナナ off YYY県産 Cさん

はじめに、flagの空欄を埋めます。
今回は、同じ行内で最後に登場した値を引き継ぐことにします。

table_flag AS (
  SELECT
    id,
    name,
    CASE
      -- flagがNULLならば、
      WHEN flag IS NULL
        -- id順で並べた際に、flagの行内で最後にNULLではなかった値を現在の行にコピーする。
        THEN LAST_VALUE(flag IGNORE NULLS) OVER (ORDER BY id)
      ELSE flag
    END AS flag0,
    pre,
    producer
  FROM base_table
)

※IGNORE NULLS:NULLを値に含まない
※LAST_VALUE ⇔ FIRST_VALUE

id name flag pre producer
1 ミカン on XXX県産 Aさん
2 ミカン on 不明 Aさん
3 リンゴ off 不明 Cさん
4 リンゴ off YYY県産 Bさん
5 バナナ off 不明 Cさん

次に、preが不明になっている欄を補完します。
今回は以下の条件に沿って進めます。
(1)同じ果物なら同じ産地である。
(2)異なる果物でも、同じ生産者なら同じ産地である。
行の順番に依存している部分がありますが、説明のために用意したテーブルなので無視します。

(1)同じ果物なら同じ産地である。

table_pre1 AS (
  SELECT
    id,
    name,
    flag0 AS flag,
    CASE
      -- 現在の行が「不明」で、
      WHEN pre = "不明"
        -- 現在の行と1つ下の行の果物が同じで、
        AND name = LEAD (name, 1) OVER (ORDER BY id)
        -- 現在の行の1つ下の行の産地が「不明」でないなら、
        AND LEAD (pre, 1) OVER (ORDER BY id) != "不明"
        -- 現在の行の1つ下の行の産地を現在の行にコピーする。
        THEN LEAD (pre, 1) OVER (ORDER BY id)
      -- 現在の行が「不明」で、
      WHEN pre = "不明"
        -- 現在の行と1つ上の行の果物が同じで、
        AND name = LAG (name, 1) OVER (ORDER BY id)
        -- 現在の行の1つ上の行の産地が「不明」でないなら、
        AND LAG (pre, 1) OVER (ORDER BY id) != "不明"
        -- 現在の行の1つ上の行の産地を現在の行にコピーする。
        THEN LAG (pre, 1) OVER (ORDER BY id)
      -- どちらにも当てはまらないなら現在の値のまま
      ELSE pre
    END AS pre0,
    producer
  FROM table_flag
)
id name flag pre producer
1 ミカン on XXX県産 Aさん
2 ミカン on XXX県産 Aさん
3 リンゴ off YYY県産 Cさん
4 リンゴ off YYY県産 Bさん
5 バナナ off 不明 Cさん

まだ1件「不明」が残っています。

(2)異なる果物でも、同じ生産者なら同じ産地である。

table_pre2 AS (
  SELECT
    id,
    name,
    flag,
    CASE
      -- table_pre1とほぼ同じなので説明省略
      WHEN pre0 = "不明"
        AND producer = LEAD (producer, 1) OVER (ORDER BY id)
        AND LEAD (pre0, 1) OVER (ORDER BY id) != "不明"
        THEN LEAD (pre0, 1) OVER (ORDER BY id)
      WHEN pre0 = "不明"
        AND producer = LAG (producer, 1) OVER (ORDER BY id)
        AND LAG (pre0, 1) OVER (ORDER BY id) != "不明"
        THEN LAG (pre0, 1) OVER (ORDER BY id)
      ELSE pre0
    END AS pre,
    producer
  FROM table_pre1
)
id name flag pre producer
1 ミカン on XXX県産 Aさん
2 ミカン on XXX県産 Aさん
3 リンゴ off YYY県産 Cさん
4 リンゴ off YYY県産 Bさん
5 バナナ off YYY県産 Cさん

これで完成です。

1
1
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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?