Дата пола в SQL server


в SQL Server, как мне " пол " DATETIME на второй/минута/час/день/год?

допустим, что у меня есть дата 2008-09-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 65

9 ответов:

ключ должен использовать 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. Поэтому выберите известное значение, которое гарантированно будет ниже, чем дата-время, которое вы пытаетесь установить.

в SQL Server вот небольшой трюк, чтобы сделать это:

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

вы бросаете DateTime в float, который представляет дату как целочисленную часть и время как часть прошедшего дня. Отрежьте эту десятичную часть, затем отбросьте ее назад к дате-времени, и у вас будет полночь в начале того дня.

Это, вероятно, более эффективно, чем все материалы DATEADD и DATEDIFF. Это, конечно, намного проще печатать.

расширяя решение Convert/Cast, в Microsoft SQL Server 2008 Вы можете сделать следующее:

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

просто заменить getdate() С любым столбцом, который является datetime.

в этом преобразовании нет строк.

это нормально для специальных запросов или обновлений, но для ключевых соединений или сильно используемой обработки может быть лучше обрабатывать преобразование в процессе обработки или переопределять таблицы, чтобы иметь соответствующие ключи и данные.

В 2005 году вы можете использовать более грязный пол:cast(floor(cast(getdate() as float)) as datetime)

Я не думаю, что это также использует преобразование строк, но я не могу говорить о сравнении фактической эффективности с оценками кресла.

я использовал @Портман много раз на протяжении многих лет в качестве ссылки, когда напольные покрытия даты и переместили свою работу в функцию, которую вы можете найти полезным.

Я не претендую на его производительность и просто предоставляю его в качестве инструмента для пользователя.

Я спрашиваю, что, если вы решите повысить этот ответ, Пожалуйста, также повысьте @Портман, как мой код является производным его.

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

жаль, что это не Oracle, иначе вы могли бы использовать trunc() или to_char().

но у меня были аналогичные проблемы с SQL Server и я использовал методы CONVERT () и DateDiff (), как указано здесь

есть несколько способов, чтобы кожа Этот кот =)

select convert(datetime,convert(varchar,CURRENT_TIMESTAMP,101))

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

источник

поскольку PostgreSQL также является "SQL Server", я упомяну

date_trunc()

который делает именно то, что вы просите изящно.

например:

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