从字符串 (t-sql) 中随时间检索不同格式的日期值
retrieve different format of date values with time from string (t-sql)
我有一个要求,我必须从字符串中提取 date/time 值,但问题是它们可以是不同的格式,因为哪个子字符串变得更复杂。
这是我想出的,但有没有其他方法可以简单地随时间检索不同格式的日期并将它们全部转换为单一格式?
IF OBJECT_ID('tempdb..#temp') IS NOT NULL
DROP TABLE #temp
CREATE TABLE #temp (
comments varchar(500)
)
insert into #temp (comments)
(
select 'Mailed on 1/1/22 at 5 pm'
union
select 'Mailed on 01/2/2222 @ 6 am'
union
select 'Mailed on 01/2/22 in night'
union
select 'Mailed on 1/02/2222 at 4 pm'
union
select 'Mailed on 1/1/2222 at 4 pm'
);
select *
from #temp
cross apply (select PATINDEX('%Mailed On%',comments) as start_pos) as start_pos
cross apply (select case when substring(comments,patindex('%Mailed On%',comments)+9,11) like '%[0-9][0-9]/[0-9][0-9]/[0-9][0-9][0-9][0-9]%' then 1
when substring(comments,patindex('%Mailed On%',comments)+9,8) like '%[0-9][0-9]/[0-9]/[0-9][0-9]%' then 2
when substring(comments,patindex('%Mailed On%',comments)+9,10) like '%[0-9]/[0-9][0-9]/[0-9][0-9][0-9][0-9]%' then 3
when substring(comments,patindex('%Mailed On%',comments)+9,9) like '%[0-9][0-9]/[0-9][0-9]/[0-9][0-9]%' then 4
when substring(comments,patindex('%Mailed On%',comments)+9,9) like '%[0-9]/[0-9]/[0-9][0-9][0-9][0-9]%' then 5
when substring(comments,patindex('%Mailed On%',comments)+9,7) like '%[0-9]/[0-9]/[0-9][0-9]%' then 6 else null end as substr) as substr
--cross apply (select case when substring(authcomments,start_pos + 9, 11) like '%[1-9]/[0123][0-9]/[0-9][0-9][0-9][0-9]%' then 1 else null end as substr) as substr
cross apply (select case when substr = 1 then substring(comments,patindex('%Mailed On%',comments)+9,11)
when substr = 2 then substring(comments,patindex('%Mailed On%',comments)+9,8)
when substr = 3 then substring(comments,patindex('%Mailed On%',comments)+9,10)
when substr = 4 then substring(comments,patindex('%Mailed On%',comments)+9,9)
when substr = 5 then substring(comments,patindex('%Mailed On%',comments)+9,9)
when substr = 6 then substring(comments,patindex('%Mailed On%',comments)+9,7)
else null end as maileddate
) as maileddate
@user1672315 ,
有时你会得到这样的东西,为了修复它,这样你就可以得到日期和时间来存储在 table 或其他什么地方,你必须做你必须做的才能得到它,而且,与评论相反,它当然可以在 SQL 中完成。这并不难。你只需要了解一些“gazintas”;)
因此,使用您提供的易于使用的测试数据,运行 针对它的以下代码...
SELECT t.*
,TheDateAndTime = DATEADD(hh,ca4.cHour,ca3.cDate)
FROM #temp t
CROSS APPLY(VALUES(SUBSTRING(comments,PATINDEX('%[0-9]%',comments),500))) ca1(DT)
CROSS APPLY(VALUES(SUBSTRING(ca1.dt,PATINDEX('% [0-9]%',ca1.dt),500))) ca2(TM)
CROSS APPLY(VALUES(TRY_CONVERT(DATETIME,SUBSTRING(ca1.DT,1,PATINDEX('%[0-9] %',ca1.DT))))) ca3(cDate)
CROSS APPLY(VALUES(IIF(ca2.TM LIKE '%night%',23,DATEPART(hh,TRY_CONVERT(DATETIME,ca2.TM)))))ca4(cHour)
;
...并看到您可以在 SQL 中做到这一点...但是,请参阅下图下方的警告。
您还需要弄清楚要分配的“晚上”时间。我指定了“23”作为小时。
结果如下:
不过,我认为您的“2222”年是错误的。 :D
我同意的一件事是格式需要保持一致。当 dd 和 mm 都小于 13 时,世界上没有任何代码,Python 或其他代码能够区分 mm-dd-yy 和 dd-mm-yy 格式。我发布的代码假定 (m )m-(d)d-yy 并且基于我正在使用的当前 LANGUAGE 和 DATEFORMAT。如果 mm 部分不在 1 到 12 之间,或者 dd 部分不在 1 到 31 之间,或者日期是“非法日期”,如 2/29/2021 等,它将 return NULL,不过
它还假定格式将始终包含数字日期作为它遇到的第一组数值,并且时间将始终是字符串中的最后一个内容。如果需要,我们可以添加更多检查,但是,就像我说的,除非 mm >=13,否则它不能(也不能)确定它应该是 mm-dd-yy 还是 dd-mm-yy 因为根本没有其他字符串中的信息以指示正在使用哪种格式。您也必须检查您的日期格式才能使用它。如果字符串应该采用 dd-mm-yy 格式,我们可能必须进行更改(尽管我相信 SQL 服务器将 auto-magically 适应如果 DATEFORMAT 符合字符串的意图).
我有一个要求,我必须从字符串中提取 date/time 值,但问题是它们可以是不同的格式,因为哪个子字符串变得更复杂。
这是我想出的,但有没有其他方法可以简单地随时间检索不同格式的日期并将它们全部转换为单一格式?
IF OBJECT_ID('tempdb..#temp') IS NOT NULL
DROP TABLE #temp
CREATE TABLE #temp (
comments varchar(500)
)
insert into #temp (comments)
(
select 'Mailed on 1/1/22 at 5 pm'
union
select 'Mailed on 01/2/2222 @ 6 am'
union
select 'Mailed on 01/2/22 in night'
union
select 'Mailed on 1/02/2222 at 4 pm'
union
select 'Mailed on 1/1/2222 at 4 pm'
);
select *
from #temp
cross apply (select PATINDEX('%Mailed On%',comments) as start_pos) as start_pos
cross apply (select case when substring(comments,patindex('%Mailed On%',comments)+9,11) like '%[0-9][0-9]/[0-9][0-9]/[0-9][0-9][0-9][0-9]%' then 1
when substring(comments,patindex('%Mailed On%',comments)+9,8) like '%[0-9][0-9]/[0-9]/[0-9][0-9]%' then 2
when substring(comments,patindex('%Mailed On%',comments)+9,10) like '%[0-9]/[0-9][0-9]/[0-9][0-9][0-9][0-9]%' then 3
when substring(comments,patindex('%Mailed On%',comments)+9,9) like '%[0-9][0-9]/[0-9][0-9]/[0-9][0-9]%' then 4
when substring(comments,patindex('%Mailed On%',comments)+9,9) like '%[0-9]/[0-9]/[0-9][0-9][0-9][0-9]%' then 5
when substring(comments,patindex('%Mailed On%',comments)+9,7) like '%[0-9]/[0-9]/[0-9][0-9]%' then 6 else null end as substr) as substr
--cross apply (select case when substring(authcomments,start_pos + 9, 11) like '%[1-9]/[0123][0-9]/[0-9][0-9][0-9][0-9]%' then 1 else null end as substr) as substr
cross apply (select case when substr = 1 then substring(comments,patindex('%Mailed On%',comments)+9,11)
when substr = 2 then substring(comments,patindex('%Mailed On%',comments)+9,8)
when substr = 3 then substring(comments,patindex('%Mailed On%',comments)+9,10)
when substr = 4 then substring(comments,patindex('%Mailed On%',comments)+9,9)
when substr = 5 then substring(comments,patindex('%Mailed On%',comments)+9,9)
when substr = 6 then substring(comments,patindex('%Mailed On%',comments)+9,7)
else null end as maileddate
) as maileddate
@user1672315 ,
有时你会得到这样的东西,为了修复它,这样你就可以得到日期和时间来存储在 table 或其他什么地方,你必须做你必须做的才能得到它,而且,与评论相反,它当然可以在 SQL 中完成。这并不难。你只需要了解一些“gazintas”;)
因此,使用您提供的易于使用的测试数据,运行 针对它的以下代码...
SELECT t.*
,TheDateAndTime = DATEADD(hh,ca4.cHour,ca3.cDate)
FROM #temp t
CROSS APPLY(VALUES(SUBSTRING(comments,PATINDEX('%[0-9]%',comments),500))) ca1(DT)
CROSS APPLY(VALUES(SUBSTRING(ca1.dt,PATINDEX('% [0-9]%',ca1.dt),500))) ca2(TM)
CROSS APPLY(VALUES(TRY_CONVERT(DATETIME,SUBSTRING(ca1.DT,1,PATINDEX('%[0-9] %',ca1.DT))))) ca3(cDate)
CROSS APPLY(VALUES(IIF(ca2.TM LIKE '%night%',23,DATEPART(hh,TRY_CONVERT(DATETIME,ca2.TM)))))ca4(cHour)
;
...并看到您可以在 SQL 中做到这一点...但是,请参阅下图下方的警告。
您还需要弄清楚要分配的“晚上”时间。我指定了“23”作为小时。
结果如下:
不过,我认为您的“2222”年是错误的。 :D
我同意的一件事是格式需要保持一致。当 dd 和 mm 都小于 13 时,世界上没有任何代码,Python 或其他代码能够区分 mm-dd-yy 和 dd-mm-yy 格式。我发布的代码假定 (m )m-(d)d-yy 并且基于我正在使用的当前 LANGUAGE 和 DATEFORMAT。如果 mm 部分不在 1 到 12 之间,或者 dd 部分不在 1 到 31 之间,或者日期是“非法日期”,如 2/29/2021 等,它将 return NULL,不过
它还假定格式将始终包含数字日期作为它遇到的第一组数值,并且时间将始终是字符串中的最后一个内容。如果需要,我们可以添加更多检查,但是,就像我说的,除非 mm >=13,否则它不能(也不能)确定它应该是 mm-dd-yy 还是 dd-mm-yy 因为根本没有其他字符串中的信息以指示正在使用哪种格式。您也必须检查您的日期格式才能使用它。如果字符串应该采用 dd-mm-yy 格式,我们可能必须进行更改(尽管我相信 SQL 服务器将 auto-magically 适应如果 DATEFORMAT 符合字符串的意图).