问题:
目标是将 SQL Server 中的临时表列 TempExpirationDate 从 NVARCHAR 更新为 DATETIME,然后使用这些值更新我的实际表。 列中的日期值有多种格式,需要转换为标准 DATETIME 格式。它基本上是一个从网站上废弃的列,必须经过大量清理才能采用日期时间格式。
待解决的问题: 尽管进行了多次调整,但某些特定的日期格式并未成功转换,即使它们看起来应该如此。
虽然大多数日期值已成功转换为 DATETIME,但特定情况(例如“2018 年 7 月 4 日”)仍会导致 NULL。 尽管对 CASE 条件进行了调整,但确定这些案例中失败的具体原因仍存在挑战。
我正在解析这样开始的数据(此日期列中不同类型值的示例)
2013-09-23 00:00:00
NULL
July 2 2022
NULL
May 5, 2015),
January 25, 2018.
March 7, 2019
January 8, 2019
September 8, 2019
April 5 2021
January 8 2021
May 8, 2019 (
April 06 2023
January 14, 2023
July 15, 2022
July 4, 2018
February 2016)
我运行以下查询,通过删除我们看到的不同格式情况的特殊字符来帮助清理日期。
UPDATE #TempIntermediateResults
SET TempExpirationDate =
CASE
-- Do nothing if the date is in the format '2013-09-23 00:00:00'
WHEN TempExpirationDate LIKE '%[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]%'
THEN TempExpirationDate
-- Leave as null if the date is null
WHEN TempExpirationDate IS NULL
THEN NULL
-- Remove special characters for month and year format like 'February 2016)'
WHEN CHARINDEX(')', TempExpirationDate) > 0
THEN LTRIM(RTRIM(REPLACE(SUBSTRING(TempExpirationDate, 1, CHARINDEX(')', TempExpirationDate)), ')', '')))
-- Remove special characters for formats like 'May 8, 2019 (' or 'May 5, 2015),'
WHEN CHARINDEX('(', TempExpirationDate) > 0
THEN LTRIM(RTRIM(REPLACE(SUBSTRING(TempExpirationDate, 1, CHARINDEX('(', TempExpirationDate)), '(', '')))
-- Remove special characters for other cases, including "."
ELSE LTRIM(RTRIM(REPLACE(REPLACE(TempExpirationDate, SUBSTRING(TempExpirationDate, PATINDEX('%[^a-zA-Z0-9 ]%', TempExpirationDate + '0'), 1), ''), '.', '')))
END;
结果是这样的:
"2013-09-23 00:00:00"
NULL
"July 4 2018 "
"July 2 2022"
"February 2016"
NULL
"May 5, 2015"
"January 25 2018"
"March 7 2019 "
"January 8 2019 "
"September 8 2019 "
"April 5 2021"
"January 8 2021"
"May 8, 2019"
"April 06 2023"
"January 14 2023"
"July 15 2022"
接下来,我运行另一个更新查询来尝试将这些值更新为日期/时间格式。
-- Update the temporary table
UPDATE #TempIntermediateResults
SET TempExpirationDate =
CASE
-- Existing conditions
WHEN TRY_CAST(TempExpirationDate AS DATETIME) IS NOT NULL
THEN TRY_CAST(TempExpirationDate AS DATETIME)
WHEN CHARINDEX(',', TempExpirationDate) > 0
THEN TRY_CAST(REPLACE(TempExpirationDate, ',', '') AS DATETIME)
WHEN CHARINDEX(')', TempExpirationDate) > 0
THEN TRY_CAST(REPLACE(SUBSTRING(TempExpirationDate, 1, CHARINDEX(')', TempExpirationDate)), ')', '') AS DATETIME)
WHEN CHARINDEX(' ', LTRIM(RTRIM(TempExpirationDate))) > 0
THEN TRY_CAST(REPLACE(LTRIM(RTRIM(TempExpirationDate)), ' ', '') AS DATETIME)
ELSE '2000-12-31T00:00:00' -- Default value if none of the conditions match. DID THIS AS A TEST VALUE TO TROUBLESHOOT IF I WOULD GET THIS DATE INSTEAD OF NULL.
END;
但是,我的结果如下:
Sep 23 2013 12:00AM
Dec 31 2000 12:00AM
NULL
Jul 2 2022 12:00AM
Feb 1 2016 12:00AM
Dec 31 2000 12:00AM
May 5 2015 12:00AM
Jan 25 2018 12:00AM
NULL
NULL
NULL
Apr 5 2021 12:00AM
Jan 8 2021 12:00AM
May 8 2019 12:00AM
Apr 6 2023 12:00AM
Jan 14 2023 12:00AM
Jul 15 2022 12:00AM
我不知道为什么下面的值总是为空,而它应该正确格式化为日期/时间,或者如果我没有正确处理它,至少设置为“2000-12-31T00:00:00”。我认为这可能是空白,但我已经通过多种方式对其进行了测试,它似乎并没有影响空值的显示。
"July 4 2018 "
"March 7 2019 "
"January 8 2019 "
"September 8 2019 "
请帮忙。
我没有看到任何明显的问题,但我自己也做过类似的练习,可以提供一些提示。
当您进行数据清理时,以小步骤进行并保存中间结果以用于调试目的非常有帮助。
我的建议是,不要一遍又一遍地更新同一列,而是将每个步骤的结果保存到新的临时表中,或者将它们存储在自己的列中。
避免将多个操作合并为一个,例如
TRY_CAST(REPLACE(SUBSTRING(TempExpirationDate, 1, CHARINDEX(')', TempExpirationDate)), ')', '') AS DATETIME)
应该是两个单独的步骤:
REPLACE(SUBSTRING(TempExpirationDate, 1, CHARINDEX(')', TempExpirationDate)), ')', '')
- 删除无效字符如果您遵循这些建议,您应该能够很容易地发现问题。