在 SQL DB2 中,我如何破译可以是 YYYYMMDD 或 YYYYMMDD 的日期字符串

Posted

技术标签:

【中文标题】在 SQL DB2 中,我如何破译可以是 YYYYMMDD 或 YYYYMMDD 的日期字符串【英文标题】:In SQL DB2, how can I decypher a date string that can be either in YYYYMMDD or YYYYDDMM 【发布时间】:2021-07-07 07:59:12 【问题描述】:

正式问题

    我正在寻找一种从varchar 列中获取日期的方法,其中的值有时格式为“YYYYMMDD”,有时格式为“YYYYDDMM”。我很清楚 20210101 是模棱两可的,但我无法更正数据,因此我任意选择在可能的情况下偏爱“MMdd”而不是“ddMM”。第一种格式在 DB 中似乎确实更丰富。

    有人能告诉我TIMESTAMP_FORMAT 在无法将字符串转换为日期时的行为吗?我期望一个 NULL 值,但事实并非如此。

更多细节,以及我尝试了什么

我正在使用一个表格,其中日期编码为整数(20211231 代表“2021-12-31”),这似乎是一种相当经典的编码。我的问题是编码格式似乎没有什么一致性:有时月份在中间(20211231),有时在月底(20213112)。

我实际上是在用 squirrel 绘制查询草图并发现 TIMESTAMP_FORMAT 有时会返回明显的 NULL 值时发现了这个事实。

举个例子:

WITH mydates(d) AS (VALUES 20211231,20213112)
SELECT 
    DATE(TIMESTAMP_FORMAT(CHAR(d),'YYYYMMDD')) AS dates
FROM mydates

结果

dates
2021-12-31
<null>

因此我认为我可以通过类似的方式克服这种情况

WITH mydates(d) AS (VALUES 20211231,20213112)
SELECT 
    COALESCE( DATE(TIMESTAMP_FORMAT(CHAR(d),'YYYYMMDD')), DATE(TIMESTAMP_FORMAT(CHAR(d),'YYYYDDMM')), DATE('0001-01-01') ) AS dates
FROM mydates

with mydates(d) as (values 20211231,20213112)
SELECT (CASE WHEN d1 IS NULL THEN d2 ELSE d1 END) AS dates FROM (
    SELECT 
        DATE(TIMESTAMP_FORMAT(CHAR(d),'YYYYMMDD')) AS d1 ,
        DATE(TIMESTAMP_FORMAT(CHAR(d),'YYYYDDMM')) AS d2
    FROM mydates
    ) tmp_dates

WITH mydates(d) AS (VALUES 20211231,20213112)
SELECT 
    (CASE WHEN DATE(TIMESTAMP_FORMAT(CHAR(d),'YYYYMMDD')) IS NULL THEN DATE(TIMESTAMP_FORMAT(CHAR(d),'YYYYDDMM')) ELSE DATE(TIMESTAMP_FORMAT(CHAR(d),'YYYYMMDD')) END) AS dates
FROM mydates

但所有查询都返回与第一个相同的结果,除了最后一个根本不起作用并以错误消息结束。

我猜TIMESTAP_FORMAT 并没有真正返回 NULL 值,我对它在错误时返回什么值以及如何解决问题一无所知。

【问题讨论】:

虽然我不知道 db2,但您从第一个 sql 中获得了 2 行。您可以考虑排除带有 NULL 的记录,例如 WITH mydates(d) AS (VALUES 20211231,20213112) SELECT DATE(TIMESTAMP_FORMAT(CHAR(d),'YYYYMMDD')) AS dates FROM mydates WHERE dates is not null。此外,您可以使用NVL。例如,SELECT NVL(DATE(TIMESTAMP_FORMAT(CHAR(20211231),'YYYYMMDD')), DATE(TIMESTAMP_FORMAT(CHAR(20213112),'YYYYMMDD'))) NVL 似乎不是我系统上的常规标量函数,但它看起来像 COALESCE 函数:返回第一个非空参数。感谢您的建议,但在我的情况下它不起作用,因为它看起来像 TIMESTAMP_FUNCTION 实际上并没有返回 NULL 值:/ @Benjaminschwarz。 . . 20210201 是什么日期?是在一月还是二月? @GordonLinoff :我很清楚这个问题。由于这似乎是最具代表性的格式,我们决定在两者都有意义的情况下任意选择 MMdd 而不是 ddMM。 【参考方案1】:

你不能 20210102 - 1 月 2 日还是 2 月 1 日? 20210510 - 5 月 10 日还是 10 月 5 日? ...

每个月有 12 天,您无法确定日期的格式。这是 365 天中的 144 天。

您需要更正您的数据,以便每个日期的格式都相同。

【讨论】:

是的,我知道这个问题,尽管我没有计算歧义区域,感谢您指出这一点。 40%确实很多!不幸的是,数据校正不是一种选择,因此我们随意选择了 MMdd 而不是 ddMM,因为这种格式在 DB 中似乎更丰富。【参考方案2】:

我设法通过检查中间的两个数字来绕过这个问题:

WITH mydates(d) AS (VALUES 20211231,20213112)
SELECT
    (CASE WHEN INTEGER(SUBSTR(CHAR(d),5,2))<=12 THEN DATE(TIMESTAMP_FORMAT(CHAR(d),'YYYYMMDD')) ELSE  DATE(TIMESTAMP_FORMAT(CHAR(d),'YYYYDDMM')) END )
from mydates

虽然这在我的情况下确实有效,但解决方案尝起来很苦,我仍然不知道假空值会发生什么。

【讨论】:

我在我的系统上查看了这个问题并遇到了同样的问题。似乎 TIMESTAMP_FORMAT 实际上并没有返回 null 而是返回一些其他无效值。我认为 Squirrel 在看到它时会将其转换为 null,但实际的 IBMi 过程会返回其他内容。我尝试在 ACS 中运行它并在无效值上获得一堆“+”(类似于“++++++++”)。我真的没有比你已经想出的更好的解决方案了。 我得出了同样的结论。此外,同时我意识到,虽然它产生了结果,但当squirrel遇到无法通过所需格式格式化的链时,它也会返回错误代码(SQLState:01534 ErrorCode:180)。【参考方案3】:

STRSQL 的行为与 JDBC 不同:拒绝执行示例查询

    WITH mydates(d) AS (VALUES 20211231,20213112)
    SELECT DATE(TIMESTAMP_FORMAT(CHAR(d),'YYYYMMDD')) AS dates
    FROM mydates

无法运行查询。查看较低级别的消息。

CPF426B 函数 TIMESTAMP_FORMAT 无法运行。 函数 TIMESTAMP_FORMAT 无法运行,原因代码为 13 13 -- 时间戳字符串不能被格式字符串解释 指定。

【讨论】:

以上是关于在 SQL DB2 中,我如何破译可以是 YYYYMMDD 或 YYYYMMDD 的日期字符串的主要内容,如果未能解决你的问题,请参考以下文章

请问DB2里面的SQL查询语句按周分组是怎么写的

在 db2 中将字符串日期(yyyy/mm/dd)转换为日期格式

powerdesign12.5如何安装和破译汉化

DB2 sql计算时间差和格式化时间

关于一个DB2 按照日期分组的问题求解

在db2中,如何使用sql查询最新七天的数据