在 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 的日期字符串的主要内容,如果未能解决你的问题,请参考以下文章