75

在 SQL Server 中,如何将 DATETIME 设置为秒/分钟/小时/天/年?

假设我有一个日期2008-09-17 12:56:53.430,那么 floor 的输出应该是:

  • 年份:2008-01-01 00:00:00.000
  • 月份:2008-09-01 00:00:00.000
  • 日期:2008-09-17 00:00:00.000
  • 时间:2008-09-17 12:00:00.000
  • 分钟:2008-09-17 12:56:00.000
  • 第二:2008-09-17 12:56:53.000
4

9 回答 9

109

关键是使用DATEADDDATEDIFF以及适当的 SQL 时间跨度枚举。

declare @datetime datetime;
set @datetime = getdate();
select @datetime;
select dateadd(year,datediff(year,0,@datetime),0);
select dateadd(month,datediff(month,0,@datetime),0);
select dateadd(day,datediff(day,0,@datetime),0);
select dateadd(hour,datediff(hour,0,@datetime),0);
select dateadd(minute,datediff(minute,0,@datetime),0);
select dateadd(second,datediff(second,'2000-01-01',@datetime),'2000-01-01');
select dateadd(week,datediff(week,0,@datetime),-1); --Beginning of week is Sunday
select dateadd(week,datediff(week,0,@datetime),0); --Beginning of week is Monday

请注意,当您按秒计算时,如果使用 0,通常会出现算术溢出。因此,请选择一个已知值,该值保证低于您尝试计算的日期时间。

于 2008-09-17T17:01:36.500 回答
30

在 SQL Server 中,有一个小技巧可以做到这一点:

SELECT CAST(FLOOR(CAST(CURRENT_TIMESTAMP AS float)) AS DATETIME)

您将 DateTime 转换为浮点数,它将 Date 表示为整数部分,将 Time 表示为一天中过去的分数。去掉那个小数部分,然后把它转换回一个 DateTime,你就在那天开始时得到了午夜。

这可能比所有 DATEADD 和 DATEDIFF 的东西更有效。打字当然更容易。

于 2008-09-17T19:08:32.403 回答
12

扩展 Convert/Cast 解决方案,在 Microsoft SQL Server 2008 中,您可以执行以下操作:

cast(cast(getdate() as date) as datetime)

只需替换getdate()为日期时间的任何列。

此转换不涉及字符串。

这对于临时查询或更新是可以的,但对于键连接或大量使用的处理,最好在处理中处理转换或重新定义表以具有适当的键和数据。

在 2005 年,您可以使用 messier 地板:cast(floor(cast(getdate() as float)) as datetime)

我不认为这也使用字符串转换,但我不能说比较实际效率与扶手椅估计。

于 2012-04-18T15:20:00.317 回答
6

多年来,我多次使用@Portman 的答案作为铺地日期的参考,并将其工作转移到您可能会发现有用的功能中。

我不声称它的性能,只是将它作为用户的工具提供。

我问,如果你决定支持这个答案,也请支持@Portman的答案,因为我的代码是他的衍生代码。

IF OBJECT_ID('fn_FloorDate') IS NOT NULL DROP FUNCTION fn_FloorDate
SET ANSI_NULLS OFF
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE FUNCTION [dbo].[fn_FloorDate] (
  @Date DATETIME = NULL,
  @DatePart VARCHAR(6) = 'day'
)
RETURNS DATETIME
AS
BEGIN
  IF (@Date IS NULL)
    SET @Date = GETDATE();

  RETURN
  CASE
    WHEN LOWER(@DatePart) = 'year' THEN DATEADD(YEAR, DATEDIFF(YEAR, 0, @Date), 0)
    WHEN LOWER(@DatePart) = 'month' THEN DATEADD(MONTH, DATEDIFF(MONTH, 0, @Date), 0)
    WHEN LOWER(@DatePart) = 'day' THEN DATEADD(DAY, DATEDIFF(DAY, 0, @Date), 0)
    WHEN LOWER(@DatePart) = 'hour' THEN DATEADD(HOUR, DATEDIFF(HOUR, 0, @Date), 0)
    WHEN LOWER(@DatePart) = 'minute' THEN DATEADD(MINUTE, DATEDIFF(MINUTE, 0, @Date), 0)
    WHEN LOWER(@DatePart) = 'second' THEN DATEADD(SECOND, DATEDIFF(SECOND, '2000-01-01', @Date), '2000-01-01')
    ELSE DATEADD(DAY, DATEDIFF(DAY, 0, @Date), 0)
  END;
END

用法:

DECLARE @date DATETIME;
SET @date = '2008-09-17 12:56:53.430';

SELECT
  @date AS [Now],--2008-09-17 12:56:53.430
  dbo.fn_FloorDate(@date, 'year') AS [Year],--2008-01-01 00:00:00.000
  dbo.fn_FloorDate(default, default) AS [NoParams],--2013-11-05 00:00:00.000
  dbo.fn_FloorDate(@date, default) AS [ShouldBeDay],--2008-09-17 00:00:00.000
  dbo.fn_FloorDate(@date, 'month') AS [Month],--2008-09-01 00:00:00.000
  dbo.fn_FloorDate(@date, 'day') AS [Day],--2008-09-17 00:00:00.000
  dbo.fn_FloorDate(@date, 'hour') AS [Hour],--2008-09-17 12:00:00.000
  dbo.fn_FloorDate(@date, 'minute') AS [Minute],--2008-09-17 12:56:00.000
  dbo.fn_FloorDate(@date, 'second') AS [Second];--2008-09-17 12:56:53.000
于 2013-07-25T14:22:45.573 回答
2

CONVERT()函数也可以执行此操作,具体取决于您使用的样式。

于 2008-09-17T17:04:00.003 回答
1

太糟糕了,它不是 Oracle,否则你可以使用 trunc() 或 to_char()。

但是我在 SQL Server 上遇到了类似的问题,并使用了 CONVERT() 和 DateDiff() 方法,如此处所引用

于 2008-09-17T17:27:37.530 回答
0

有几种方法可以给这只猫剥皮 =)

select convert(datetime,convert(varchar,CURRENT_TIMESTAMP,101))
于 2014-10-02T17:27:12.570 回答
0

DateAdd 和 DateDiff 可以帮助完成许多不同的任务。例如,您可以找到任何一个月的最后一天,也可以找到上个月或下个月的最后一天。

----Last Day of Previous Month
SELECT DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,GETDATE()),0))
LastDay_PreviousMonth
----Last Day of Current Month
SELECT DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,GETDATE())+1,0))
LastDay_CurrentMonth
----Last Day of Next Month
SELECT DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,GETDATE())+2,0))
LastDay_NextMonth

来源

于 2016-05-05T20:19:22.040 回答
-1

由于 PostgreSQL 也是一个“SQL Server”,我会提到

date_trunc()

这正是您优雅地要求的。

例如:

选择 date_trunc('hour',current_timestamp);
       日期截断
----------------------
 2009-02-18 07:00:00-08
(1 行)

于 2009-02-18T15:46:30.357 回答