【问题标题】:Snowflake ignores statement in where clause where I'm comparing timestampsSnowflake 忽略了我比较时间戳的 where 子句中的语句
【发布时间】:2021-08-24 15:16:46
【问题描述】:

所以我在雪花中构建了一个 SCD 类型 2,但它忽略了比较“to_timestamp”和“expiry_date”的 where 子句。 Expiry_date 是一个设置为 '9999-08-17 07:31:29.901000000' 的变量(如无穷大),而 To_timestamp 是表中的一列。我只想查询 to_timestamp 设置为无穷大的行(它们仍然处于活动状态),但雪花似乎忽略了 where 子句的这一部分。下面是一些代码(它应该更新过期的行 - 这意味着将它们的“to_timestamp”更改为当前时间。它确实如此,但它对具有各种时间戳的行 - 它忽略了最后一行)

SET EXPIRY_DATE_NTZ = '9999-08-17 07:31:29.901000000';
SET CURRENT_DATE_NTZ = TO_TIMESTAMP_NTZ(CURRENT_TIMESTAMP());


UPDATE CUSTOMER_TARGET CT
SET CT.TO_TIMESTAMP = $CURRENT_DATE_NTZ
FROM POC.SNOWFLAKE_POC.CUSTOMER_STAGE CS
WHERE CT.C_CUSTOMER_ID = CS.C_CUSTOMER_ID
    AND (CT.C_FIRST_NAME <> CS.C_FIRST_NAME OR CT.C_LAST_NAME <> CS.C_LAST_NAME OR CT.C_BIRTH_YEAR 
    <> CS.C_BIRTH_YEAR OR CT.C_BIRTH_COUNTRY <> CS.C_BIRTH_COUNTRY OR CT.C_LAST_REVIEW_DATE<>CS.C_LAST_REVIEW_DATE)
    AND CT.TO_TIMESTAMP = $EXPIRY_DATE_NTZ;

我有两个更新语句(一个用于更新,一个用于删除)和一个用于插入的合并语句。它忽略了每一个比较,将“to_timestamp”设置为“2021-08-24 07:11:53.510000000”之类的行更新。我已经尝试了所有可能的组合(在...和...之间,>= ... =,在更新的“case”语句中进行比较,...) - 没有。可能是什么原因/解决方案?

【问题讨论】:

  • 我想“忽略”意味着没有行匹配过滤器,并且没有太多行受到影响。为什么不将所有相关的当前活动行的“无穷大”值设置为“9999-12-31 23:59:59”,并将其也用于比较?或者,您可以使用仅适用于当前值的布尔值 is_current,并在更新过程中将 to_timestampis_current 设置为正确的值。
  • 该列实际上是否称为“to_timestamp”?使用函数名作为列名并不是一个好的设计,它会让你的代码更加混乱。

标签: sql timestamp compare snowflake-cloud-data-platform equals


【解决方案1】:

由于我们不知道CUSTOMER_TARGET的结构,我建议显式设置EXPIRY_DATE_NTZ变量的数据类型以匹配列数据类型:

SET EXPIRY_DATE_NTZ = '9999-08-17 07:31:29.901000000';
SELECT $EXPIRY_DATE_NTZ;
DESCRIBE RESULT LAST_QUERY_ID();

到:

-- TIMESTAMP_NTZ as an example
SET EXPIRY_DATE_NTZ = '9999-08-17 07:31:29.901000000'::TIMESTAMP_NTZ;  
SELECT $EXPIRY_DATE_NTZ;
DESCRIBE RESULT LAST_QUERY_ID();

通过这种方式,过程中不涉及“隐式转换”。


另一个建议是使用IS DISTINCT FROM 而不是&lt;&gt;IS DISTINCT FROM 是 NULL 安全的,如果列被定义为可为空,这一点很重要。

UPDATE CUSTOMER_TARGET CT
SET CT.TO_TIMESTAMP = $CURRENT_DATE_NTZ
FROM POC.SNOWFLAKE_POC.CUSTOMER_STAGE CS
WHERE CT.C_CUSTOMER_ID = CS.C_CUSTOMER_ID
    AND (CT.C_FIRST_NAME IS DISTINCT FROM CS.C_FIRST_NAME 
         OR CT.C_LAST_NAME IS DISTINCT FROM CS.C_LAST_NAME 
         OR CT.C_BIRTH_YEAR IS DISTINCT FROM CS.C_BIRTH_YEAR 
         OR CT.C_BIRTH_COUNTRY IS DISTINCT FROM CS.C_BIRTH_COUNTRY 
         OR CT.C_LAST_REVIEW_DATE IS DISTINCT FROM CS.C_LAST_REVIEW_DATE)
    AND CT.TO_TIMESTAMP = $EXPIRY_DATE_NTZ;

【讨论】:

    【解决方案2】:

    您的 SQL 对过滤器没有任何问题(OR 被括号等包围)。我假设您已经检查了执行配置文件,但没有看到您的过滤器 (CT.TO_TIMESTAMP = '9999-08-17 07:31:29.901000000')。在这种情况下,目标表中的所有行都应在 TO_TIMESTAMP 列中具有此值。

    我强烈建议您先检查数据。如果您正在运行多个 UPDATE/MERGE 命令,您可能会错过已使用此值更新的数据。

    【讨论】:

      猜你喜欢
      • 2012-03-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-09
      • 2015-01-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多