【问题标题】:How do I handle exception while converting date转换日期时如何处理异常
【发布时间】:2021-08-13 09:42:03
【问题描述】:

我有一个Sales 表和一个Period 表。

销售表

+--------------+-------------+
| Country_Code | Period_Code |
+--------------+-------------+
| CH           | MAI_18      |
| CH           | JUN_18      |
| NO           | 2020-01-21  |
| NO           | 2020-01-21  |
+--------------+-------------+

周期表

+--------------+-------------+
| Country_Code | Period_Code |
+--------------+-------------+
| NO           | 200121      |
| NO           | 200122      |
+--------------+-------------+

我在加入这 2 个表时收到以下错误。

下面是我使用的sql。据我了解,由于我在第二行将国家过滤器指定为NO,因此它应该首先执行第二行,然后仅在NO 国家/地区进行连接。但在内部,它正在考虑 CH 国家/地区,这也导致以下 sql 失败。

SELECT DISTINCT SAL.COUNTRY_CODE,PER.PERIOD_CODE
FROM (SELECT * FROM MYSCHEMA.SALES WHERE COUNTRY_CODE in('NO')) SAL
JOIN MYSCHEMA.PERIOD PER 
    ON SAL.COUNTRY_CODE=PER.COUNTRY_CODE    
    AND TO_CHAR(TO_DATE(SAL.PERIOD_CODE,'YYYY-MM-DD'),'YYMMDD') = PER.PERIOD_CODE
ORDER BY 1

我也使用了CTE,它的行为方式也相同。可能有一些解决方案。如果有人可以帮助我让 sql 运行而不会出现任何错误,我将不胜感激。

【问题讨论】:

  • 如果您期望输出和可能的 db fiddle,会更容易提供帮助。
  • 预期输出不是这里的问题。担心的是sql抛出错误。我需要让这个 sql 运行没有任何错误。
  • SQL 没有定义执行顺序,它可以评估条件并以任何顺序执行计算——只定义了结果集。我不知道您的 SQL 可能性;在某些平台上您可以使用try_convert(),在某些平台上您应该使用某种case 表达式来排除转换非法条目的可能性。

标签: sql join snowflake-cloud-data-platform date-conversion inner-query


【解决方案1】:

Snowflake 比 SQL 规范声明更早地显式进行转换,因此文本/变量数据的转换在您预期之前发生。我在 2016 年向他们提出了这个问题,虽然他们有时会修复/更改某些行为,但它也可能会改变并因此开始破坏。

如果列的内容并非全部有效,这是您的情况,您应该使用TRY_版本的命令,因此这里使用TRY_TO_DATE以避免错误。

因此您应该会发现这是可行的:

SELECT DISTINCT SAL.COUNTRY_CODE,PER.PERIOD_CODE
FROM (SELECT * FROM MYSCHEMA.SALES WHERE COUNTRY_CODE in('NO')) SAL
JOIN MYSCHEMA.PERIOD PER 
    ON SAL.COUNTRY_CODE=PER.COUNTRY_CODE    
    AND TO_CHAR(TRY_TO_DATE(SAL.PERIOD_CODE,'YYYY-MM-DD'),'YYMMDD') = PER.PERIOD_CODE
ORDER BY 1

我倾向于将日期转换移动到子选择中(或 CTE,如果您使用其中之一)以使连接更简单,尽管 Snowflake 会为您执行此操作,因此我会这样写:

SELECT DISTINCT sal.country_code,
    per.period_code
FROM (
    SELECT country_code,
        TO_CHAR(TRY_TO_DATE(SAL.PERIOD_CODE,'YYYY-MM-DD'),'YYMMDD') AS join_code
    FROM myschema.sales 
    WHERE country_code in ('NO')
) sal
JOIN myschema.period per 
    ON sal.country_code = per.country_code    
    AND sal.join_code = per.period_code
ORDER BY 1

但鉴于您的示例表,我假设它不包含所有列,只是重现问题所需的,应该能够通过以下方式触发:

SELECT country_code,
    TO_CHAR(TRY_TO_DATE(SAL.PERIOD_CODE,'YYYY-MM-DD'),'YYMMDD') AS join_code
FROM myschema.sales 
WHERE country_code in ('NO')

【讨论】:

  • 谢谢西蒙。像魅力一样工作。 +1 @Simeon Pilgrim
猜你喜欢
  • 2018-09-15
  • 2018-11-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-01
  • 1970-01-01
  • 2012-11-17
  • 2019-02-18
相关资源
最近更新 更多