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

在MS SQL 2000和2005中,给定date时间如“2008-09-25 12:34:56”什么是最有效的方式来获取仅包含“2008-09-25”的date时间?

重复在这里 。

我必须承认我之前并没有看到马特所performance出的场内浮动转换。 我必须testing这个。

我testing了一个纯粹的select(它将返回date和时间,而不是我们想要的),这里的统治解决scheme(floor-float),这里提到的一个常见的“天真”(stringconvert)和这里提到的我使用(因为我认为这是最快的)。

我testing了运行在Win 2003 SP2服务器上的testing服务器MS SQL Server 2005上的查询,最大内存上运行至强3GHz CPU(32位,因此大约为3.5 Gb)。 这是我的夜晚,所以机器几乎没有负载的情况下空转。 我已经掌握了一切。

下面是从我的testing运行中select一个包含时间戳到毫秒级别的大表中的日志。 这个特定的数据集包括超过2.5年的date。 桌子本身有超过一亿三千万行,所以这就是为什么我限制在百万。

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行受影响)Table'tblMeasureLogv2'。 扫描计数1,逻辑读取4752,物理读取0,预读读取0,lob逻辑读取0,lob物理读取0,lob预读读取0。

SQL Server执行时间:CPU时间= 422毫秒,经过时间= 33803毫秒。

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

SQL Server执行时间:CPU时间= 625毫秒,经过时间= 33545毫秒。

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

SQL Server执行时间:CPU时间= 1953毫秒,经过时间= 33843毫秒。

(1000000行受影响)Table'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毫秒。

我们在这里看到什么?

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

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

从这个angular度来看,像DateAdd(至less在这种特殊情况下)比地板式方法稍快。

在你去那里之前,我跑了几次这个testing,查询的顺序改变了,结果也是一样的。

这在我的服务器上有点奇怪吗?

 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日。净效应就是除去时间成分。

我还应该提到,这种方法适用于任何date/时间部分(如年,季,月,日,时,分,秒)。

 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日,你会得到一个错误。

两个date时间列的差异导致运行时溢出。

您可以通过使用不同的参考date(如2000年1月1日)来绕过这个错误。

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

因为将date时间转换为浮点数给出了自1900年1月1日以来的天数(包括一天中的小数部分)。地面数据删除了小数天数,并留下了整天的天数,然后可以转换回date时间。

在SQL Server 2012中使用

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

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

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

编辑:糟糕,他想要一个DateTime而不是一个string。 在Oracle中相当于TRUNC()。 你可以把我发布的内容转换回DateTime:

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

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

如何仅从SQL Server datetime数据types返回date部分

下面的链接中描述了三种方法。 我没有性能testing,以确定哪个是最快的。

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

CAST(FLOOR(CAST(yourdate AS DECIMAL(12, 5))) AS DATETIME)performance最好。 你可以看到在没有时间在sql server中获取date的certificate和testing

什么关于SELECT CAST(CASt(GETDATE() AS int) AS DATETIME)

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