LoginSignup
0
0

More than 1 year has passed since last update.

【BQとSnowflakeのSQL】で格闘した話

Last updated at Posted at 2023-04-07

概要

BigQueryとSnowflakeのSQLとで書き方や関数の仕様の違いによりSQLと格闘したので備忘録として。

UNNESTとFLATTEN(配列の展開方法)

BQの場合

SELECT
	user_id
	,unnest_column
FROM
	table
,UNNEST(nested_column) AS unnest_column

Snowflakeの場合
TABLE関数とFLATTEN関数を組み合わせて、名前を付けておき、「名前.value」で配列を展開することができる

SELECT
	user_id
	,tn.value AS unnest_column
FROM
	table
TABLE(FLATTEN(table.nested_column)) tn

関数定義(UDF)

BQの場合

create temporary function FUNC() as ('処理の中身');

Snowflakeの場合
型を定義し、「$$」で囲む必要がある

create or replace function FUNC() RETURNS varchar as $$ ('処理の中身') $$;

時刻の差分計算の違い

BQとSnowflakeの時刻の差分掲載は動作が異なるため要注意。個人的にSnowflake側の動作がクセあるなと思いました。

「DAY」単位での差分を計算することを例にしてBQ、Snowflakeの動作をそれぞれ示します。

BQ

BQの場合(23時間59分59秒のズレがある時)

SELECT
  DATE_DIFF('2023-05-09 T 23:39:19'
          , '2023-05-08 T 23:39:20'
          , DAY) AS time_diffence

アウトプットは、「time_diffence --> 0」

BQの場合(24時間0分0秒のズレがある時)

SELECT
  DATE_DIFF('2023-05-09 T 23:39:20'
          , '2023-05-08 T 23:39:20'
          , DAY) AS time_diffence

アウトプットは、「time_diffence --> 1」

BQの場合(24時間0分1秒のズレがある時)

SELECT
  DATE_DIFF('2023-05-09 T 23:39:21'
          , '2023-05-08 T 23:39:20'
          , DAY) AS time_diffence

アウトプットは、「time_diffence --> 1」

Snowflake

Snowflakeの場合(23時間59分59秒のズレがある時)

SELECT
  DATEDIFF(DAY
  		  ,'2023-05-08 T 23:39:20'
          , '2023-05-09 T 23:39:19'
          ) AS time_diffence

アウトプットは、「time_diffence --> 1」

1日経っていないが、time_differenceが1になってしまう。これがややこしい。

Snowflakeの場合(24時間0分0秒のズレがある時)

SELECT
  DATEDIFF(DAY
  		  ,'2023-05-08 T 23:39:20'
          , '2023-05-09 T 23:39:20'
          ) AS time_diffence

アウトプットは、「time_diffence --> 1」

Snowflakeの場合(24時間0分1秒のズレがある時)

SELECT
  DATEDIFF(DAY
  		  ,'2023-05-08 T 23:39:20'
          , '2023-05-09 T 23:39:21'
          ) AS time_diffence

アウトプットは、「time_diffence --> 1」

SnowflakeのDATEDIFF関数では、指定している単位(今回は「DAY」)の数値のズレを計算するため、BQとは異なる結果が出力される。

そのため、例えば、5月8日の23時39分20秒と日付が変わった瞬間の時刻の差分を計算すると、実際には20分程度しかたっていないにもかかわらず、

SELECT
  DATEDIFF(DAY
  		  ,'2023-05-08 T 23:39:20'
          , '2023-05-09 T 00:00:00'
          ) AS time_diffence

アウトプットは、「time_diffence --> 1」となってしまう。

ちなみに、次の場合はDAYが変わっていないので、time_differenceは0となる。

SELECT
  DATEDIFF(DAY
  		  ,'2023-05-08 T 23:39:20'
          , '2023-05-08 T 23:59:59'
          ) AS time_diffence

アウトプットは、「time_diffence --> 0」となる。

BQと同じような出力結果を出すのであれば、
①時間単位を秒単位(SECOND)に設定して何秒の時間差があるかを計算
②①で出した秒数を24×60×60(=24時間の秒数)で割り算する。
③割り算結果の整数部分(例えば2.3であれば、”2”)をtime_differenceに保持する
という処理をすることでBQと同じ結果を出すことができる。

ので、例えば、23時間59分59秒のズレがある時

SELECT
TRUNCATE (
  DIV0NULL (
      DATEDIFF( SECOND
              , '2023-05-08 T 23:39:20'
              , '2023-05-09 T 23:39:19'
              ), 24*60*60
            ), 0
         ) AS time_diffence

こうすれば、アウトプットは「time_diffence --> 0」となり、BQと同じ結果を得ることができる。

また、日付が変わった瞬間の時刻の差分でも

SELECT
TRUNCATE (
  DIV0NULL (
      DATEDIFF( SECOND
              , '2023-05-08 T 23:39:20'
          		'2023-05-09 T 00:00:00'
              ), 24*60*60
            ), 0
         ) AS time_diffence

こうすれば、アウトプットは「time_diffence --> 0」となり、BQと同じ結果を得ることができる。

BOOLEANの違い

WHERE句でBOOLEANのカラムで絞り込みをする場合、BQでは「IS TRUE」と書けるがSnowflakeでは「= TRUE」にしないといけない。

BQ

SELECT COUNT(*)
FROM table
WHERE column1 IS TRUE AND column2 IS NULL

Snowflake

SELECT COUNT(*)
FROM table
WHERE column1 = TRUE AND column2 IS NULL

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