各位老大,字段格式由由字符串轉變成時間類型的問題


有一數據庫,大概有一萬條記錄,里面有個字段是用來定位時間的,但最開始設計數據庫的時候把這個字段的格式設置為字符串類型的,而且也沒有做非空驗證,導致現在這個字段的記錄里,大概有5000條是符合時間格式的如“2008-08-08”,也有幾千條是"2008/8/8"這種格式,更多的是其他亂七八糟的字符串或空值,如下:
table1
-----------------------------
uid  name  begintime
-----------------------------
001  aaaa  2008-08-08
002  bbbb  2008-8-8
003  cccc  2008/8/8
004  dddd  2008-08-08
005  eeee  aaaaaaa
006  ffff  (空值)
007  gggg  AAAA-bb-asdflekf
------------------------------
以上為部分數據示例,總數有五六千條是不規范的。

我的問題是,在begintime字段中選擇出距某一時刻有三年的數據,比如距2008-08-08這一天三年內的,即(2005-08-08到2008-08-07)這一時間段的數據。

這問題好像挺麻煩的,那么,如果不考慮非時間格式的數據,只考慮能轉換成時間格式的數據的行,但是是字符串格式的字段,應如何選擇呢?

6 个解决方案

#1


 

create table table1 (uid varchar(3),name varchar(4),begintime varchar(16))
go
insert into table1
select '001','aaaa','2003-08-08' union all
select '002','bbbb','2006-8-8' union all
select '003','cccc','2008/8/8' union all
select '004','dddd','2008-08-08' union all
select '005','eeee','aaaaaaa' union all
select '006','ffff','(空值)' union all
select '007','gggg','AAAA-bb-asdflekf'


select * into # from table1 where isdate(begintime)=1
select * from # where datediff(yy,begintime,'2008-08-08')<=3

/*
002 bbbb 2006-8-8
003 cccc 2008/8/8
004 dddd 2008-08-08
*/

#2



   select * from table1 where isdate(begintime)=1
   and dateadd(year,3,cast(begintime as datetime)<'2008-08-08'

#3


create table tb(uid varchar(10), name varchar(10), begintime varchar(20)) 
insert into tb values('001' , 'aaaa' , '2008-08-08') 
insert into tb values('002' , 'bbbb' , '2008-8-8') 
insert into tb values('003' , 'cccc' , '2008/8/8') 
insert into tb values('004' , 'dddd' , '2008-08-08') 
insert into tb values('005' , 'eeee' , 'aaaaaaa') 
insert into tb values('006' , 'ffff' , null )
insert into tb values('007' , 'gggg' , 'AAAA-bb-asdflekf') 
go

select * from tb where isdate(begintime) = 1
/*
uid        name       begintime            
---------- ---------- -------------------- 
001        aaaa       2008-08-08
002        bbbb       2008-8-8
003        cccc       2008/8/8

(所影響的行數為 3 行)
*/

select * from 
(
select uid , name , 
       case when isdate(begintime) = 1 and ((datediff(yy,begintime,'2008-08-08') <= 2) or (datediff(yy,begintime,'2008-08-08') = 3 and right(convert(varchar(10),begintime,120),5) >= '08-08' ) ) then begintime 
       else '' end begintime
from tb
) t
where begintime <> ''
/*
uid        name       begintime            
---------- ---------- -------------------- 
001        aaaa       2008-08-08
002        bbbb       2008-8-8
003        cccc       2008/8/8

(所影響的行數為 3 行)
*/


drop table tb

#4


樓上的老大,

select * from 
(
select uid , name , 
       case when isdate(begintime) = 1 and ((datediff(yy,begintime,'2008-08-08') <= 2) or (datediff(yy,begintime,'2008-08-08') = 3 and right(convert(varchar(10),begintime,120),5) >= '08-08' ) ) then begintime 
       else '' end begintime
from tb
) t
where begintime <> ''


改寫成

select uid , name , 
       case when isdate(begintime) = 1 and ((datediff(yy,begintime,'2008-08-08') <= 2) or (datediff(yy,begintime,'2008-08-08') = 3 and right(convert(varchar(10),begintime,120),5) >= '08-08' ) ) then begintime 
       else '' end begintime

from tb
where begintime <> ''

為什么不行呢?空值也會顯示出來。

#5


一樓的朋友
select * from # where datediff(yy,begintime,'2008-08-08')<=3
這個會把2005-01-01的也選擇了,已經超過三年了。

二樓的朋友的代碼
select * from table1 where isdate(begintime)=1
   and dateadd(year,3,cast(begintime as datetime)<'2008-08-08

無法執行,我把全角的標點都改成半角了,語法正確了,但顯示無法轉換成datetime類型。。

#6


select * 
from 
  (select * from tb where isnumeric(left(begintime,4)) = 1) a
where 
  begintime between '2005-8-8' and '2008-8-7'

注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com