代码之家  ›  专栏  ›  技术社区  ›  Portman

SQL Server中的楼层日期

  •  65
  • Portman  · 技术社区  · 16 年前

    在SQL Server中,如何将日期时间“地板”为秒/分钟/小时/天/年?

    假设我有一个约会 2008年9月17日12:56:53.430 ,则地板产量应为:

    • 年份: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
    9 回复  |  直到 16 年前
        1
  •  93
  •   Davin Studer    7 年前

    关键是要用 DATEADD DATEDIFF 以及适当的SQL TimeSpan枚举。

    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,通常会出现算术溢出。因此,选择一个已知的值,该值一定要低于您要创建的日期时间。

        2
  •  28
  •   Chris Wuestefeld    16 年前

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

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

    您将日期时间转换为一个浮点,它将日期表示为整数部分,时间表示为经过的一天的分数。把小数部分切掉,然后把它转换回日期时间,你就得到了当天开始时的午夜。

    这可能比所有的dateadd和datediff工具更有效。打字当然容易。

        3
  •  11
  •   Charles Menguy jdw6415    12 年前

    在转换/转换解决方案的基础上展开,在Microsoft SQL Server 2008中,可以执行以下操作:

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

    只是替换 getdate() 任何列都是日期时间。

    此转换中不涉及字符串。

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

    2005年,您可以使用更凌乱的地板: cast(floor(cast(getdate() as float)) as datetime)

    我也不认为这会用到字符串转换,但是我不能用实际的效率和扶手椅的估算值来比较。

        4
  •  6
  •   Community Jaime Torres    7 年前

    我已经用过 @Portman's answer 多年来,作为一个参考,地板日期和工作转移到一个你可能会发现有用的功能。

    我并没有宣称它的性能,只是把它作为一个工具提供给用户。

    我问你,如果你决定投反对票,请也投反对票。 @波特曼的回答 因为我的代码是他的派生代码。

    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
    
        5
  •  2
  •   Joel Coehoorn    16 年前

    这个 CONVERT() 函数也可以这样做,这取决于您使用的样式。

        6
  •  1
  •   typicalrunt    16 年前

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

    但我在SQL Server上也有类似的问题,并使用了convert()和datediff()方法,正如引用的那样。 here

        7
  •  0
  •   Leistungsabfall    10 年前

    有几种方法可以剥下这只猫的皮。

    select convert(datetime,convert(varchar,CURRENT_TIMESTAMP,101))
    
        8
  •  0
  •   pinaldave    8 年前

    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
    

    Source

        9
  •  -2
  •   wogsland    8 年前

    因为PostgreSQL也是一个“SQL服务器”,我会提到

    date_trunc()
    

    这完全符合你的要求。

    例如:

     select date_trunc('hour',current_timestamp);
           date_trunc
    ------------------------
     2009-02-18 07:00:00-08
    (1 row)