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

时间:2020-03-06 14:43:04  来源:igfitidea点击:

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

在这里重复。

解决方案

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日,则会收到错误消息。

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

我们可以使用其他参考日期来避免该错误(例如2000年1月1日)。

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

之所以有效,是因为将日期时间强制转换为浮点型可给出自1900年1月1日以来的天数(包括一天的小数部分)。对其进行地板处理将除去小数天,剩下整天的数目,然后可以将其转换回日期时间。

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

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

编辑:糟糕,他想要一个DateTime而不是一个字符串。与Oracle中的TRUNC()等效。我们可以将我发布的内容投射回DateTime:

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

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

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

如何仅从SQL Server datetime数据类型返回日期部分

下面的链接中介绍了三种方法。我尚未对它们进行性能测试以确定最快的方法。

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

我必须承认,我以前从未见过Matt展示的下浮率转换。我不得不对此进行测试。

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

我在运行Win 2003 SP2服务器的测试服务器MS SQL Server 2005上测试了查询,该服务器在最大内存(32位,因此约为3.5 Gb)上运行了Xeon 3GHz CPU。那天晚上我在这里,所以机器几乎没有负载空转。我已经掌握了一切。

这是我的测试运行中的日志,该日志是从一个大表中选择的,该表包含从毫秒到毫秒的时间戳。这个特定的数据集包含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 parse and compile time:     CPU time = 0 ms, elapsed time = 1 ms.
  
  (1000000 row(s) affected) Table 'tblMeasureLogv2'. Scan count 1, logical reads 4752, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
  
  SQL Server Execution Times:    CPU time = 422 ms,  elapsed time = 33803 ms.
  
  (1000000 row(s) affected) Table 'tblMeasureLogv2'. Scan count 1, logical reads 4752, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
  
  SQL Server Execution Times:    CPU time = 625 ms,  elapsed time = 33545 ms.
  
  (1000000 row(s) affected) Table 'tblMeasureLogv2'. Scan count 1, logical reads 4752, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
  
  SQL Server Execution Times:    CPU time = 1953 ms,  elapsed time = 33843 ms.
  
  (1000000 row(s) affected) Table 'tblMeasureLogv2'. Scan count 1, logical reads 4752, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
  
  SQL Server Execution Times:    CPU time = 531 ms,  elapsed time = 33440 ms. SQL Server parse and compile time: CPU time = 0 ms, elapsed time = 1 ms.
  
  SQL Server Execution Times:    CPU time = 0 ms,  elapsed time = 1 ms.

我们在这里看到什么?

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

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

由此看来,DateAdd(至少在这种情况下)比现场直播方法要快一些。

在我们去那里之前,我多次运行了此测试,查询的顺序已更改,结果相同。

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

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

`CAST(FLOOR(CAST(yourdate AS DECIMAL(12,5)))AS DATETIME)在目前为止表现最好。我们可以在SQL Server中获取没有时间的日期时看到的证明和测试