在 Snowflake JOIN 条件下强制使用 UTC 时间
Force UTC time in Snowflake JOIN condition
我有一个设置
- 具有类型 TIMESTAMP_LTZ (consumption_date) 的栏的登陆 table。包括时区 +02:00
- 从着陆读取的视图(landing_view)table
- 从具有类型 TIMESTAMP_NTZ (SOURCE_TIMESTAMP) 字段的 table 读取的视图 (raw_data),但值本身采用 UTC 时间.
我必须使用 consumption_date 和 SOURCE_TIMESTAMP 将 landing_view 中的数据连接到 raw_data 中的数据。
SELECT l.ID, l.consumption_date, l.RUN_TIME, r.DISPLAY_NAME, r.source_timestamp, r.value_as_double
FROM "raw_data" r
JOIN "landing_view" l
ON r.SOURCE_TIMESTAMP >= DATEADD(second,120, convert_timezone('UTC',l.consumption_date))
and r.SOURCE_TIMESTAMP < DATEADD(second,1000, convert_timezone('UTC',l.consumption_date))
我的问题是 convert_timezone 命令似乎根本不影响连接子句,而是使用 LTZ 类型 (+02:00) 中包含的本地时间进行连接。
如果我使用 convert_timezone 是 select,如果工作正常,但对于 JOIN 则不行。
有什么方法可以告诉 snowflake 在连接中使用 UTC?
这取决于您的时区设置。请参阅下面的示例。
如果时区是 UTC:
alter session set TIMEZONE = 'UTC';
select
-- 2AM UTC
'2021-01-02 02:00:00'::timestamp_ntz as SOURCE_TIMESTAMP,
-- 1AM UTC / 12PM Australia/Melbourne time / 1 hour before SOURCE_TIMESTAMP
'2021-01-02 12:00:00 +1100'::timestamp_ltz as CONSUMPTION_DATE,
-- so add one hour to CONSUMPTION_DATE should equal to SOURCE_TIMESTAMP
SOURCE_TIMESTAMP = DATEADD(hour, 1, convert_timezone('UTC', CONSUMPTION_DATE)) as is_equal
;
+-------------------------------+-------------------------------+----------+
| SOURCE_TIMESTAMP | CONSUMPTION_DATE | IS_EQUAL |
|-------------------------------+-------------------------------+----------|
| 2021-01-02 02:00:00.000000000 | 2021-01-02 01:00:00.000 +0000 | True |
+-------------------------------+-------------------------------+----------+
但是,如果您将 TIMEZONE 设置更改为另一个时区,结果将有所不同:
alter session set TIMEZONE = 'Australia/Melbourne';
select
-- 2AM UTC
'2021-01-02 02:00:00'::timestamp_ntz as SOURCE_TIMESTAMP,
-- 1AM UTC / 12PM Australia/Melbourne time / 1 hour before SOURCE_TIMESTAMP
'2021-01-02 12:00:00 +1100'::timestamp_ltz as CONSUMPTION_DATE,
-- so add one hour to CONSUMPTION_DATE should equal to SOURCE_TIMESTAMP
SOURCE_TIMESTAMP = DATEADD(hour, 1, convert_timezone('UTC', CONSUMPTION_DATE)) as is_equal
;
+-------------------------------+-------------------------------+----------+
| SOURCE_TIMESTAMP | CONSUMPTION_DATE | IS_EQUAL |
|-------------------------------+-------------------------------+----------|
| 2021-01-02 02:00:00.000000000 | 2021-01-02 12:00:00.000 +1100 | False |
+-------------------------------+-------------------------------+----------+
由于您 SOURCE_TIMESTAMP 存储了 UTC 值,您应该更改您的 TIMEZONE 设置以匹配它。
顺便说一句,在 DATEADD 中加入 CONVERT_TIMEZONE 是多余的,因为它只是增加了额外的操作,但没有任何效果。请参阅以下示例:
select
-- 1AM UTC / 9AM Australia/Perth time / 1 hour before SOURCE_TIMESTAMP
'2021-01-02 09:00:00 +0800'::timestamp_ltz as CONSUMPTION_DATE,
DATEADD(hour, 1, CONSUMPTION_DATE) as no_convert_tz,
DATEADD(hour, 1, convert_timezone('UTC', CONSUMPTION_DATE)) as convert_tz,
no_convert_tz = convert_tz
;
+-------------------------------+-------------------------------+-------------------------------+----------------------------+
| CONSUMPTION_DATE | NO_CONVERT_TZ | CONVERT_TZ | NO_CONVERT_TZ = CONVERT_TZ |
|-------------------------------+-------------------------------+-------------------------------+----------------------------|
| 2021-01-02 12:00:00.000 +1100 | 2021-01-02 13:00:00.000 +1100 | 2021-01-02 02:00:00.000 +0000 | True |
+-------------------------------+-------------------------------+-------------------------------+----------------------------+
您可以看到最后一列 returns 正确。
我有一个设置
- 具有类型 TIMESTAMP_LTZ (consumption_date) 的栏的登陆 table。包括时区 +02:00
- 从着陆读取的视图(landing_view)table
- 从具有类型 TIMESTAMP_NTZ (SOURCE_TIMESTAMP) 字段的 table 读取的视图 (raw_data),但值本身采用 UTC 时间.
我必须使用 consumption_date 和 SOURCE_TIMESTAMP 将 landing_view 中的数据连接到 raw_data 中的数据。
SELECT l.ID, l.consumption_date, l.RUN_TIME, r.DISPLAY_NAME, r.source_timestamp, r.value_as_double
FROM "raw_data" r
JOIN "landing_view" l
ON r.SOURCE_TIMESTAMP >= DATEADD(second,120, convert_timezone('UTC',l.consumption_date))
and r.SOURCE_TIMESTAMP < DATEADD(second,1000, convert_timezone('UTC',l.consumption_date))
我的问题是 convert_timezone 命令似乎根本不影响连接子句,而是使用 LTZ 类型 (+02:00) 中包含的本地时间进行连接。
如果我使用 convert_timezone 是 select,如果工作正常,但对于 JOIN 则不行。
有什么方法可以告诉 snowflake 在连接中使用 UTC?
这取决于您的时区设置。请参阅下面的示例。
如果时区是 UTC:
alter session set TIMEZONE = 'UTC';
select
-- 2AM UTC
'2021-01-02 02:00:00'::timestamp_ntz as SOURCE_TIMESTAMP,
-- 1AM UTC / 12PM Australia/Melbourne time / 1 hour before SOURCE_TIMESTAMP
'2021-01-02 12:00:00 +1100'::timestamp_ltz as CONSUMPTION_DATE,
-- so add one hour to CONSUMPTION_DATE should equal to SOURCE_TIMESTAMP
SOURCE_TIMESTAMP = DATEADD(hour, 1, convert_timezone('UTC', CONSUMPTION_DATE)) as is_equal
;
+-------------------------------+-------------------------------+----------+
| SOURCE_TIMESTAMP | CONSUMPTION_DATE | IS_EQUAL |
|-------------------------------+-------------------------------+----------|
| 2021-01-02 02:00:00.000000000 | 2021-01-02 01:00:00.000 +0000 | True |
+-------------------------------+-------------------------------+----------+
但是,如果您将 TIMEZONE 设置更改为另一个时区,结果将有所不同:
alter session set TIMEZONE = 'Australia/Melbourne';
select
-- 2AM UTC
'2021-01-02 02:00:00'::timestamp_ntz as SOURCE_TIMESTAMP,
-- 1AM UTC / 12PM Australia/Melbourne time / 1 hour before SOURCE_TIMESTAMP
'2021-01-02 12:00:00 +1100'::timestamp_ltz as CONSUMPTION_DATE,
-- so add one hour to CONSUMPTION_DATE should equal to SOURCE_TIMESTAMP
SOURCE_TIMESTAMP = DATEADD(hour, 1, convert_timezone('UTC', CONSUMPTION_DATE)) as is_equal
;
+-------------------------------+-------------------------------+----------+
| SOURCE_TIMESTAMP | CONSUMPTION_DATE | IS_EQUAL |
|-------------------------------+-------------------------------+----------|
| 2021-01-02 02:00:00.000000000 | 2021-01-02 12:00:00.000 +1100 | False |
+-------------------------------+-------------------------------+----------+
由于您 SOURCE_TIMESTAMP 存储了 UTC 值,您应该更改您的 TIMEZONE 设置以匹配它。
顺便说一句,在 DATEADD 中加入 CONVERT_TIMEZONE 是多余的,因为它只是增加了额外的操作,但没有任何效果。请参阅以下示例:
select
-- 1AM UTC / 9AM Australia/Perth time / 1 hour before SOURCE_TIMESTAMP
'2021-01-02 09:00:00 +0800'::timestamp_ltz as CONSUMPTION_DATE,
DATEADD(hour, 1, CONSUMPTION_DATE) as no_convert_tz,
DATEADD(hour, 1, convert_timezone('UTC', CONSUMPTION_DATE)) as convert_tz,
no_convert_tz = convert_tz
;
+-------------------------------+-------------------------------+-------------------------------+----------------------------+
| CONSUMPTION_DATE | NO_CONVERT_TZ | CONVERT_TZ | NO_CONVERT_TZ = CONVERT_TZ |
|-------------------------------+-------------------------------+-------------------------------+----------------------------|
| 2021-01-02 12:00:00.000 +1100 | 2021-01-02 13:00:00.000 +1100 | 2021-01-02 02:00:00.000 +0000 | True |
+-------------------------------+-------------------------------+-------------------------------+----------------------------+
您可以看到最后一列 returns 正确。