SQL Server中最有效的方法是从日期+时间获取日期?

时间:2008-09-25 12:42:01

标签: sql sql-server tsql

在MS SQL 2000和2005中,给定日期时间,例如'2008-09-25 12:34:56',获取仅包含'2008-09-25'的日期时间的最有效方法是什么?

重复here

11 个答案:

答案 0 :(得分:111)

我必须承认我之前没有看过Matt所展示的地板浮动转换。我不得不测试一下。

我测试了一个纯粹的选择(它将返回日期和时间,而不是我们想要的),这里的统治解决方案(floor-float),这里提到的常见'天真'(stringconvert)和这里提到的那个我正在使用(因为我认为它是最快的)。

我测试了运行在Win 2003 SP2服务器上的测试服务器MS SQL Server 2005上的查询,其中Xeon 3GHz CPU在最大内存(32位,大约3.5 Gb)上运行。现在是我的所在地,所以机器几乎没有负载就在空转。我已经把它全部都给了自己。

这是我的测试运行中的日志,从包含时间戳变化到毫秒级别的大型表中进行选择。该特定数据集包括超过2。5年的日期。该表本身有超过1.3亿行,所以这就是我限制在百万之前的原因。

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 ms,已用时间= 1 ms。

     

(1000000行(s)受影响)表'tblMeasureLogv2'。扫描计数1,逻辑读取4752,物理读取0,预读取读取0,lob逻辑读取0,lob物理读取0,lob预读读取0。

     

SQL Server执行时间:CPU时间= 422毫秒,已用时间= 33803毫秒。

     

(1000000行(s)受影响)表'tblMeasureLogv2'。扫描计数1,逻辑读取4752,物理读取0,预读取读取0,lob逻辑读取0,lob物理读取0,lob预读读取0。

     

SQL Server执行时间:CPU时间= 625毫秒,已用时间= 33545毫秒。

     

(1000000行(s)受影响)表'tblMeasureLogv2'。扫描计数1,逻辑读取4752,物理读取0,预读取读取0,lob逻辑读取0,lob物理读取0,lob预读读取0。

     

SQL Server执行时间:CPU时间= 1953毫秒,已用时间= 33843毫秒。

     

(1000000行(s)受影响)表'tblMeasureLogv2'。扫描计数1,逻辑读取4752,物理读取0,预读取读取0,lob逻辑读取0,lob物理读取0,lob预读读取0。

     

SQL Server执行时间:CPU时间= 531毫秒,已用时间= 33440毫秒。 SQL Server解析和编译时间:CPU时间= 0 ms,已用时间= 1 ms。

     

SQL Server执行时间:CPU时间= 0毫秒,已用时间= 1毫秒。

我们在这看到什么?

让我们关注CPU时间(我们正在考虑转换),我们可以看到我们有以下数字:

Pure-Select:  422
Floor-cast:   625
String-conv: 1953
DateAdd:      531  

从这一点来看,它看起来像DateAdd(至少在这种特殊情况下)比地板投射方法略快。

在你去那里之前,我多次运行这个测试,查询的顺序发生了变化,同样的结果。

我的服务器上有什么奇怪的东西,或者是什么?

答案 1 :(得分:23)

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日)来规避此错误。

答案 2 :(得分:12)

select cast(floor(cast(@datetime as float)) as datetime)

有效,因为将日期时间转换为浮点数会给出自1900年1月1日以来的天数(包括一天的分数)。地板会删除小数天并留下整天的天数,然后可以将其转换为日期时间。

答案 3 :(得分:7)

在SQL Server 2012中使用

select cast(getdate() as date)

答案 4 :(得分:1)

select cast(getdate()as varchar(11))as datetime

答案 5 :(得分:0)

要获得YYYY-MM-DD,请使用:

select convert(varchar(10), getdate(), 120)

编辑:哎呀,他想要一个DateTime而不是一个字符串。相当于Oracle中的TRUNC()。您可以将我发布的内容转换回DateTime:

select convert(datetime, convert(varchar(10), getdate(), 120) , 120)

答案 6 :(得分:0)

CONVERT,FLOOR和DATEDIFF将执行相同的操作。

How to return the date part only from a SQL Server datetime datatype

答案 7 :(得分:0)

以下链接中描述了三种方法。我没有对它们进行性能测试以确定哪个是最快的。

http://www.blackwasp.co.uk/SQLDateFromDateTime.aspx

答案 8 :(得分:0)

到目前为止,

CAST(FLOOR(CAST(yourdate AS DECIMAL(12, 5))) AS DATETIME)表现最佳。你可以看到证明&在getting the date without time in sql server

时进行测试

答案 9 :(得分:-1)

CONVERT(VARCHAR(10), GETDATE(), 120) AS [YYYY-MM-DD]

答案 10 :(得分:-1)

SELECT CAST(CASt(GETDATE() AS int) AS DATETIME) ??

怎么样?