ti-enxame.com

Coloque uma data no servidor SQL

No SQL Server, como faço para "floor" um DATETIME para o segundo/minuto/hora/dia/ano?

Digamos que eu tenha uma data de 2008-09-17 12: 56: 53.430 , então a saída do piso deve ser:

  • Ano: 2008-01-01 00: 00: 00.000
  • Mês: 2008-09-01 00: 00: 00.000
  • Dia: 2008-09-17 00: 00: 00.000
  • Hora: 2008-09-17 12: 00: 00.000
  • Minuto: 2008-09-17 12: 56: 00.000
  • Segunda: 2008-09-17 12: 56: 53.000
65
Portman

A chave é usar DATEADD e DATEDIFF juntamente com a enumeração de tempo de processamento SQL apropriada.

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

Note que quando você está pisando no segundo, você frequentemente obterá um estouro aritmético se você usar 0. Escolha um valor conhecido que seja garantidamente menor que o datetime que você está tentando usar.

94
Portman

No SQL Server, aqui está um pequeno truque para fazer isso:

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

Você converte o DateTime em um ponto flutuante, que representa a Data como a parte inteira e o Tempo como a fração de um dia que é passado. Cortar essa parte decimal, em seguida, elenco de volta para um DateTime, e você tem meia-noite no início do dia.

Isso provavelmente é mais eficiente que todos os itens DATEADD e DATEDIFF. Certamente é mais fácil digitar.

28
Chris Wuestefeld

Expandindo a solução Convert/Cast, no Microsoft SQL Server 2008, você pode fazer o seguinte:

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

Apenas substitua getdate() por qualquer coluna que seja um datetime.

Não há sequências envolvidas nesta conversão.

Isso é aceitável para consultas ou atualizações ad-hoc, mas para junções de chave ou processamento altamente usado, pode ser melhor manipular a conversão dentro do processamento ou redefinir as tabelas para ter chaves e dados apropriados.

Em 2005, você pode usar o andar messier: cast(floor(cast(getdate() as float)) as datetime)

Eu não acho que use conversão de string, mas eu não posso falar em comparar a eficiência real com as estimativas de poltrona.

11
Moe Cazzell

Eu usei @ resposta de Portman muitas vezes ao longo dos anos como uma referência ao pavimentar datas e ter movido seu trabalho em uma função que você pode achar útil.

Não faço reivindicações de seu desempenho e simplesmente forneço-o como uma ferramenta para o usuário.

Eu pergunto que, se você decidir votar esta resposta, por favor também upvote @ resposta de Portman , como meu código é um derivado dele.

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

Uso:

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
6
Dan Atkinson

A função CONVERT () pode fazer isso também, dependendo do estilo que você usa.

2
Joel Coehoorn

Pena que não é Oracle, senão você poderia usar trunc () ou to_char ().

Mas eu tive problemas semelhantes com o SQL Server e usei os métodos CONVERT () e DateDiff (), como referenciado aqui

1
typicalrunt

Existem várias maneiras de esfolar este gato =)

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

DateAdd junto com DateDiff pode ajudar a fazer muitas tarefas diferentes. Por exemplo, você pode encontrar o último dia de qualquer mês, bem como encontrar o último dia do mês anterior ou seguinte. 

----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

Fonte

0
pinaldave