我正在导入包含日期的CSV文件,这些文件的格式有两种:
31. 12. 2019
7/2020
这两种形式可以交替出现在同一列中;因此,解决方案的一部分必须是表单的检测。
由于第二个表单7/2020
不包含日期信息,因此我将1用作日期。
到目前为止,我只处理了使用可预测日期形式的记录子集。我遵循了CONVERT()
函数(https://docs.microsoft.com/en-us/sql/t-sql/functions/cast-and-convert-transact-sql)的T-SQL文档。假设@date = '31. 12. 2019'
然后完成以下转换:
CONVERT(date, @date, 104) AS my_date -- the German form
对于@date = '7/2020'
,请执行以下操作:
CONVERT(date, '1/' + @date, 103) AS my_date -- the British/French form
现在,如果我(事先)不知道@date
包含什么形式,该如何转换?
实际上,日期不在@date
变量中。相反,它是SELECT
查询中的字段值,例如xdate
。我希望代码看起来像这样:
CASE WHEN /* detect the British/French case */ THEN CONVERT(date, '1/' + xdate, 103)
WHEN /* detect the German case */ THEN CONVERT(date, xdate, 104)
ELSE NULL -- this does not happen, anyway...
END AS my_date
...但是可能会有更好的方法。
答案 0 :(得分:6)
如果我正确理解了这个问题,则可能的解决方案是将COALESCE()
和TRY_CONVERT()
组合在一起:
声明:
SELECT COALESCE(
TRY_CONVERT(date, xdate, 104),
TRY_CONVERT(date, '1/' + xdate, 103)
) AS xdate
FROM (VALUES
('31. 12. 2019'),
('7/2000'),
('wrong date 12/12')
) v (xdate)
结果:
xdate
----------
2019-12-31
2000-07-01
null
答案 1 :(得分:2)
简单的charindex
可以让您指示字符串是否包含斜杠(/
)-如果文本格式为m/yyyy
或{{ 1}}。
但是,您应该使用dd. mm. yyyy
而不是Try_convert
,因为不能保证case表达式会短路,这意味着可能会评估所有convert
子句。
这是我的写法:
when
答案 2 :(得分:1)
我认为您是使用批量插入或类似的过程将CSV转储到表中,并且该表中存储未处理日期的列是varchar
,然后针对表格来处理内容,是吗?
如果是这种情况,并且只有这两种形式,则可以使用like
或charindex()
。据我所知,性能几乎是相同的,因此无论哪种方法都易于阅读。我个人可能会使用charindex
:
select case
when charindex('/', xdate) > 0 then convert(date, '1/' + xdate, 103)
else convert(date, xdate, 104)
end
或使用like
:
select case
when xdate like '%/%' then convert(date, '1/' + xdate, 103)
else convert(date, xdate, 104)
end
如果这不是唯一的两种形式,那么您可能想改而try_convert
,或者只涵盖您所有的基础