场合
我正在尝试使用列名称来构造查询:TxnDate(TransactionDate),类型为INT
。典型日期如下所示:YYYYMMDD
,因此20180209
或20171025
为例。我无法改变这个事实,否则很多事情都会破裂。不幸的是,它陷入了这种愚蠢的格式。
但是,它仅对我有用,因为数据类型DATE
,所以我必须首先以迂回方式转换它:CONVERT(DATE, CONVERT(char(8), TransactionDate))
为了使事情进一步复杂化,由于各种原因,某些日期为空,负或零。因此,为了使其成为可用的形式,我需要检查以确保它可以转换:
CASE WHEN ISDATE(TxnDate)=1
THEN CONVERT(DATE, CONVERT(CHAR(8),TxnDate))
END
日期数据不佳的记录对我没用。
问题是我需要检查然后在WHERE
语句中的许多不同位置进行转换。这使我的查询膨胀到略微荒谬的比例。我希望以更清洁,更简洁的方式表达一些智慧。
我考虑的内容
我不愿意在架构中添加内容,但如果是更好的选择,我会这样做:
1)创建一个视图,为我演示,我可以从中查询,代替表格,如下所示:Is it possible to change the datatype of a column in a view?我不偏袒于此,因为尝试时可能会出现问题施放,这使整个目的无效。
2)创建一个用户定义的函数,在调用时只运行CASE
表达式。
3)我为变量尝试了许多不同的别名变体,并以许多不同的方式使用AS
表达式尝试仅在一个地方定义它,但无济于事。这可能是可能的,但我无法通过自己的努力或通过互联网搜索找到它。
同样,我很欣赏这方面的任何智慧,我是SQL新手,所以如果有明显的解决方案或重复的问题,请指出。此外,如果你觉得这个问题出了问题,我宁愿你在投票前告诉我什么是不正确的,这样我就有机会改进和学习。
谢谢
答案 0 :(得分:0)
您可以使用此测试结尾处给出的查询。我必须生成与您的规范相匹配的虚拟数据来执行测试,但您只需要生成所需日期列(Transaction_Date)的SQL。
create table #test1 (
TxnDt int
)
go
insert #test1 values(20180328) -- March 28, 2018
insert #test1 values(20170220) -- Feb 20, 2017
insert #test1 values(20161201) -- Dec 1, 2016
insert #test1 values(2016) -- bad data
insert #test1 values(1) -- data
go
select distinct * from #test1
go
TxnDt
1
2016
20161201
20170220
20180328
- 假设正确的数据将以yyyymmdd的形式存在,您可以运行以下SQL将其转换为日期类型
select *
from
(
select distinct TxnDt
, case when len(cast(TxnDt as char(8))) = 8
then convert(date,substring(cast(TxnDt as char(8)),5,2) + '/' + substring(cast(TxnDt as char(8)),7,2) + '/' + substring(cast(TxnDt as char(8)),1,4))
end as Transaction_Date
-- , case when len(substring(cast(TxnDt as char(8)),5,2) + '/' + substring(cast(TxnDt as char(8)),7,2) + '/' + substring(cast(TxnDt as char(8)),1,4)) = 10 then TxnDt end
-- , convert(date,substring(cast(TxnDt as char(8)),5,2) + '/' + substring(cast(TxnDt as char(8)),7,2) + '/' + substring(cast(TxnDt as char(8)),1,4)) TransDate
--into #test2
from #test1
) main
where main.Transaction_Date is not null
go
TxnDt Transaction_Date
20161201 2016-12-01
20170220 2017-02-20
20180328 2018-03-28