Redshift中的数据错误无效

时间:2017-09-20 17:28:23

标签: sql amazon-redshift sqldatatypes

我有一个查询我在redshift中运行,当我尝试比较两个日期时会产生错误。我已经确定这是由于数据问题,其中日期是VARCHAR,有些是空字符串。最好的解决方案显然是在源头解决这个问题,但在尝试构建一个解决方案时,我偶然发现了一些非常奇怪的行为。

为了解决这个问题,我预先选择非空字符串的日期,并将其转换为日期,然后转换为整数日期格式(YYYYMMDD)并转换为INT。这很好。但是,如果我尝试将其与WHERE子句中的整数进行比较,则查询会因数据类型错误而崩溃。

以下是工作查询的玩具版本

SELECT
    date_id,
    COUNT(*)
FROM
    (
    SELECT
        CONVERT(int, date_id) AS date_id
    FROM
        (
        SELECT
            DATE_PART('year', start_dttm)*10000+DATE_PART('month', start_dttm)*10+DATE_PART('day', start_dttm) AS date_id
        FROM        
            (
            SELECT
                CAST(start_dttm AS DATETIME) AS start_dttm
            FROM
                sfe.calendar_detail
            WHERE
                start_dttm <> ''
            ) cda
        ) cdb
    ) cd
GROUP BY
    date_id
;

这是失败的查询

SELECT
    date_id,
    COUNT(*)
FROM
    (
    SELECT
        CONVERT(int, date_id) AS date_id
    FROM
        (
        SELECT
            DATE_PART('year', start_dttm)*10000+DATE_PART('month', start_dttm)*10+DATE_PART('day', start_dttm) AS date_id
        FROM        
            (
            SELECT
                CAST(start_dttm AS DATETIME) AS start_dttm
            FROM
                sfe.calendar_detail
            WHERE
                start_dttm <> ''
            ) cda
        ) cdb
    ) cd
WHERE
    date_id >= 20170920
GROUP BY
    date_id
;

正如我上面提到的,正确的解决方案是修复数据类型并计算空日期,因为Nulls不是空字符串,但我很好奇为什么第二个查询因无效数据类型错误而崩溃。

非常感谢!

编辑: 这是错误

ERROR:  Invalid digit, Value '1', Pos 0, Type: Integer 
DETAIL:  
  -----------------------------------------------
  error:  Invalid digit, Value '1', Pos 0, Type: Integer 
  code:      1207
  context:   
  query:     2006739
  location:  :0
  process:   query0_39 [pid=0]
  -----------------------------------------------

1 个答案:

答案 0 :(得分:0)

不是将日期转换为人类可读的YYYYMMDD格式,最好将它们保持为DATETIMESTAMP格式。这样,可以容易地执行日期操作(例如,将日期添加5天)。您仍然可以使用'YYYYMMDD'::DATE进行简单的比较运算符。

鉴于您正在从String转换,并且转换为Date似乎有效,并且您有一些空字符串,请使用此字符串将其转换为日期:

SELECT
  NULLIF(start_dttm, '')::DATE AS dt
FROM sfe.calendar_detail
WHERE dt > '20170920'::DATE

如果字符串为空,则返回NULL;如果包含可以转换的日期,则返回Date。