在 SQL Server 2008 中截断日期时间值(如删除小时、分钟和秒)的最佳方法是什么?
例如:
declare @SomeDate datetime = '2009-05-28 16:30:22' select trunc_date(@SomeDate) ----------------------- 2009-05-28 00:00:00.000
这继续频繁地收集额外的选票,甚至几年后,所以我需要为现代版本的 Sql Server 更新它。对于 Sql Server 2008 及更高版本,这很简单:
cast(getDate() As Date)
请注意,靠近底部的最后三段仍然适用,并且您通常需要退后一步并找到一种方法来避免首先出现演员表。
但也有其他方法可以做到这一点。这里是最常见的。
正确的方法(自 Sql Server 2008 以来的新方法):
cast(getdate() As Date)
正确方法(旧):
dateadd(dd, datediff(dd,0, getDate()), 0)
这现在更老了,但它仍然值得了解,因为它还可以轻松适应其他时间点,例如一个月、分钟、小时或一年的第一时刻。
这种正确的方法使用作为 ansi 标准的一部分并保证可以工作的文档化函数,但它可能会慢一些。它的工作原理是找出从第 0 天到当天有多少天,然后将这些天添加回第 0 天。无论您的日期时间如何存储,也无论您的语言环境是什么,它都会起作用。
快速方法:
cast(floor(cast(getdate() as float)) as datetime)
这是因为 datetime 列存储为 8 字节二进制值。将它们转换为浮点数,将它们降低以删除分数,当您将它们转换回日期时间时,值的时间部分就消失了。这一切都只是位移,没有复杂的逻辑,而且速度 非常 快。
请注意,这依赖于 Microsoft 可以随时更改的实施细节,即使是在自动服务更新中也是如此。它也不是很便携。在实践中,这种实现不太可能很快改变,但如果你选择使用它,意识到危险仍然很重要。现在我们可以选择将其投射为日期,这几乎没有必要。
错误的方法:
cast(convert(char(11), getdate(), 113) as datetime)
错误的方法是转换为字符串、截断字符串并转换回日期时间。这是 错误 的,有两个原因:1)它可能不适用于所有语言环境和 2)它是最慢的方法......而且不仅仅是一点点;它比其他选项慢一个或两个数量级。
更新 这最近得到了一些投票,所以我想补充一点,自从我发布这个我已经看到一些非常可靠的证据表明 Sql Server 将优化“正确”方式和“快速”方式之间的性能差异,这意味着您现在应该支持前者。
在任何一种情况下,您都希望 编写查询以避免一开始就需要这样做 。您很少会在数据库上进行这项工作。
在大多数地方,数据库已经是你的瓶颈。通常,为提高性能而添加硬件最昂贵的服务器,以及最难正确添加硬件的服务器(例如,您必须平衡磁盘和内存)。从技术和商业角度来看,它也是最难向外扩展的;从技术上讲,添加 Web 或应用程序服务器比添加数据库服务器要容易得多,即使这是错误的,您也无需为 IIS 或 apache 的每个服务器许可证支付 20,000 美元以上。
我要说明的一点是,只要有可能,您就应该在应用程序级别进行这项工作。您发现自己在 Sql Server 上截断日期时间的 唯一 一次是当您需要按天分组时,即便如此,您可能应该将额外的列设置为计算列,在插入/更新时维护,或维护在应用程序逻辑中。从您的数据库中获取这种破坏索引、占用大量 CPU 资源的工作。