在 MS SQL 2000 和 2005 中,如果给出一个日期时间值如 '2008-09-25 12:34:56',最有效的方法是什么以获取只包含 '2008-09-25' 的日期时间值?
此问题已被复制到这里。
在 MS SQL 2000 和 2005 中,如果给出一个日期时间值如 '2008-09-25 12:34:56',最有效的方法是什么以获取只包含 '2008-09-25' 的日期时间值?
此问题已被复制到这里。
我必须承认,之前我从未见过Matt展示的floor-float转换方法。我不得不测试一下。
我测试了一个纯选择查询(会返回日期和时间,而这不是我们想要的),这里的主流解决方案(floor-float),一个常见的“幼稚”的方案(stringconvert)以及我曾经使用过的这个方案(因为我认为它是最快的)。
我在一个测试服务器上进行了查询,该服务器是运行在Windows Server 2003 SP2上的MS SQL Server 2005,配备一颗3GHz的Xeon CPU,并且内存达到最大值(32位系统,约为3.5 Gb)。现在是晚上,在我的机器上几乎没有负载。我独占了整个服务器。
以下是我的测试日志,选择一个包含时间戳的大表格,时间戳精确到毫秒级别。这个数据集包括超过2.5年的日期范围。这个表格本身有超过1.3亿行数据,所以我只对前100万行进行限制。
SELECT TOP 1000000 CRETS FROM tblMeasureLogv2
SELECT TOP 1000000 CAST(FLOOR(CAST(CRETS AS FLOAT)) AS DATETIME) FROM tblMeasureLogv2
SELECT TOP 1000000 CONVERT(DATETIME, CONVERT(VARCHAR(10), CRETS, 120) , 120) FROM tblMeasureLogv2
SELECT TOP 1000000 DATEADD(DAY, DATEDIFF(DAY, 0, CRETS), 0) FROM tblMeasureLogv2
SQL Server解析和编译时间:CPU时间=0毫秒,经过时间=1毫秒。
(1000000行受影响) 表'tblMeasureLogv2'。扫描计数1,逻辑读取4752,物理读取0,预读取读取0,lob逻辑读取0,lob物理读取0,lob预读取读取0。
SQL Server执行时间:CPU时间=422毫秒,经过时间=33803毫秒。
(1000000行受影响) 表'tblMeasureLogv2'。 扫描计数1,逻辑读取4752,物理读取0,预读取读取0,lob逻辑读取0,lob物理读取0,lob预读取读取0。
SQL Server执行时间:CPU时间=625毫秒,经过时间=33545毫秒。
(1000000行受影响) 表'tblMeasureLogv2'。 扫描计数1,逻辑读取4752,物理读取0,预读取读取0,lob逻辑读取0,lob物理读取0,lob预读取读取0。
SQL Server执行时间:CPU时间=1953毫秒,经过时间=33843毫秒。
(1000000行受影响) 表'tblMeasureLogv2'。 扫描计数1,逻辑读取4752,物理读取0,预读取读取0,lob逻辑读取0,lob物理读取0,lob预读取读取0。
SQL Server执行时间:CPU时间=531毫秒,经过时间=33440毫秒。 SQL Server解析和编译时间:CPU时间=0毫秒,经过时间=1毫秒。
SQL Server执行时间:CPU时间=0毫秒,经过时间=1毫秒。Pure-Select: 422
Floor-cast: 625
String-conv: 1953
DateAdd: 531
从这个结果来看,至少在这种情况下,DateAdd 的速度似乎比 floor-cast 方法稍快。
在你继续之前,我已经多次运行了此测试,并改变了查询的顺序,得到了类似的结果。
这是我的服务器出了什么问题吗?还是其他原因?
Select DateAdd(Day, DateDiff(Day, 0, GetDate()), 0)
DateDiff(Day, 0, GetDate())与DateDiff(Day, '1900-01-01', GetDate())意义相同。
由于DateDiff返回整数,您将获得自1900年1月1日以来经过的天数。然后,您将该整数天数添加到1900年1月1日。其效果是去除时间部分。
我还应该提到,此方法适用于任何日期/时间部分(例如年、季度、月、日、小时、分钟和秒)。
Select DateAdd(Year, DateDiff(Year, 0, GetDate()), 0)
Select DateAdd(Quarter, DateDiff(Quarter, 0, GetDate()), 0)
Select DateAdd(Month, DateDiff(Month, 0, GetDate()), 0)
Select DateAdd(Day, DateDiff(Day, 0, GetDate()), 0)
Select DateAdd(Hour, DateDiff(Hour, 0, GetDate()), 0)
Select DateAdd(Second, DateDiff(Second, '20000101', GetDate()), '20000101')
最后一个,即秒的处理需要特殊处理。如果使用1900年1月1日,您将会收到错误提示。
两个日期时间列的差值导致运行时溢出。
可以通过使用不同的参考日期(如2000年1月1日)来避免此错误。
select cast(floor(cast(@datetime as float)) as datetime)
这段代码的原理是将日期时间转换为浮点型,得到自1900年1月1日至今的天数(包括一部分天数的小数部分)。取整后保留完整天数,再将其转换回日期时间格式。
在 SQL Server 2012 中使用:
select cast(getdate() as date)
select cast(getdate()as varchar(11))as datetime
CAST(FLOOR(CAST(yourdate AS DECIMAL(12, 5))) AS DATETIME)
是迄今为止最好的选择。你可以在在SQL Server中获取不带时间的日期时看到证据和测试。
CONVERT、FLOOR和DATEDIFF将执行相同的操作。
要获取YYYY-MM-DD,请使用:
select convert(varchar(10), getdate(), 120)
编辑:哎呀,他想要一个DateTime而不是一个字符串。Oracle中TRUNC()的等价物。你可以拿我发布的内容并转换回DateTime:
select convert(datetime, convert(varchar(10), getdate(), 120) , 120)
关于 SELECT CAST(CASt(GETDATE() AS int) AS DATETIME)
怎么样?