Maneira mais eficiente no SQL Server para obter data de data + hora?

Em MS SQL 2000 e 2005, dado um datetime como ‘2008-09-25 12:34:56’ o que é a maneira mais eficiente para obter um datetime contendo apenas ‘2008-09-25’?

Duplicado aqui .

Devo admitir que não tinha visto a conversão de flutuação no chão mostrada por Matt antes. Eu tive que testar isso.

Eu testei um select puro (que retornará Data e Hora, e não é o que eu quero), a solução reinante aqui (floor-float), uma comum ‘ingênua’ mencionada aqui (stringconvert) e a mencionada aqui que eu estava usando (como eu pensei que fosse o mais rápido).

Testei as consultas em um servidor de teste MS SQL Server 2005 em execução em um servidor Win 2003 SP2 com uma CPU Xeon 3GHz em execução na memory máxima (32 bits, ou seja, cerca de 3,5 Gb). É noite onde eu estou assim a máquina está em marcha lenta quase sem carga. Eu tenho tudo para mim mesmo.

Aqui está o log da minha seleção de teste de uma grande tabela contendo registros de data e hora variando até o nível de milissegundos. Este dataset específico inclui datas que variam mais de 2,5 anos. A tabela em si tem mais de 130 milhões de linhas, e é por isso que eu me restrito aos milhões.

SELECT TOP 1000000 CRETS FROM tblMeasureLogv2 SELECT TOP 1000000 CAST(FLOOR(CAST(CRETS AS FLOAT)) AS DATETIME) FROM tblMeasureLogv2 SELECT TOP 1000000 CONVERT(DATETIME, CONVERT(VARCHAR(10), CRETS, 120) , 120) FROM tblMeasureLogv2 SELECT TOP 1000000 DATEADD(DAY, DATEDIFF(DAY, 0, CRETS), 0) FROM tblMeasureLogv2 

Tempo de compilation e de compilation do SQL Server: tempo de CPU = 0 ms, tempo decorrido = 1 ms.

(Linha (s) de 1000000 afetada) Tabela ‘tblMeasureLogv2’. Contagem de varreduras 1, leituras lógicas 4752, leituras físicas 0, leitura em leitura 0, leituras lógicas lob 0, lob leituras físicas 0, lob read-ahead lê 0.

Tempos de Execução do SQL Server: Tempo de CPU = 422 ms, tempo decorrido = 33803 ms.

(Linha (s) de 1000000 afetada) Tabela ‘tblMeasureLogv2’. Contagem de varreduras 1, leituras lógicas 4752, leituras físicas 0, leitura em leitura 0, leituras lógicas lob 0, lob leituras físicas 0, lob read-ahead lê 0.

Tempos de Execução do SQL Server: Tempo de CPU = 625 ms, tempo decorrido = 33545 ms.

(Linha (s) de 1000000 afetada) Tabela ‘tblMeasureLogv2’. Contagem de varreduras 1, leituras lógicas 4752, leituras físicas 0, leitura em leitura 0, leituras lógicas lob 0, lob leituras físicas 0, lob read-ahead lê 0.

Tempos de Execução do SQL Server: Tempo de CPU = 1953 ms, tempo decorrido = 33843 ms.

(Linha (s) de 1000000 afetada) Tabela ‘tblMeasureLogv2’. Contagem de varreduras 1, leituras lógicas 4752, leituras físicas 0, leitura em leitura 0, leituras lógicas lob 0, lob leituras físicas 0, lob read-ahead lê 0.

Tempos de Execução do SQL Server: Tempo de CPU = 531 ms, tempo decorrido = 33440 ms. Tempo de compilation e de compilation do SQL Server: tempo de CPU = 0 ms, tempo decorrido = 1 ms.

Tempos de Execução do SQL Server: Tempo de CPU = 0 ms, tempo decorrido = 1 ms.

O que estamos vendo aqui?

Vamos nos concentrar no tempo de CPU (estamos analisando a conversão), e podemos ver que temos os seguintes números:

 Pure-Select: 422 Floor-cast: 625 String-conv: 1953 DateAdd: 531 

A partir disso, parece-me que o DateAdd (pelo menos neste caso em particular) é um pouco mais rápido do que o método floor-cast.

Antes de você ir lá, executei esse teste várias vezes, com a ordem das consultas alteradas, resultados iguais.

Isso é algo estranho no meu servidor, ou o quê?

 Select DateAdd(Day, DateDiff(Day, 0, GetDate()), 0) 

DateDiff (dia, 0, GetDate ()) é o mesmo que DateDiff (dia, ‘1900-01-01’, GetDate ())

Como DateDiff retorna um inteiro, você obterá o número de dias decorridos desde 1º de janeiro de 1900. Você adiciona esse número inteiro de dias a 1º de janeiro de 1900. O efeito final é remover o componente de tempo.

Também devo mencionar que esse método funciona para qualquer parte de data / hora (como ano, trimestre, mês, dia, hora, minuto e segundo).

 Select DateAdd(Year, DateDiff(Year, 0, GetDate()), 0) Select DateAdd(Quarter, DateDiff(Quarter, 0, GetDate()), 0) Select DateAdd(Month, DateDiff(Month, 0, GetDate()), 0) Select DateAdd(Day, DateDiff(Day, 0, GetDate()), 0) Select DateAdd(Hour, DateDiff(Hour, 0, GetDate()), 0) Select DateAdd(Second, DateDiff(Second, '20000101', GetDate()), '20000101') 

O último, por segundos, requer manuseio especial. Se você usar 01 de janeiro de 1900, você receberá um erro.

Diferença de duas colunas datetime causou estouro no tempo de execução.

Você pode contornar esse erro usando uma data de referência diferente (como 1º de janeiro de 2000).

 select cast(floor(cast(@datetime as float)) as datetime) 

Funciona porque a conversão de um datetime em float indica o número de dias (incluindo frações de um dia) desde 1º de janeiro de 1900. O Flooring remove os dias fracionários e deixa o número de dias inteiros, que podem ser convertidos em um datetime.

no uso do SQL Server 2012

 select cast(getdate() as date) 
 select cast(getdate()as varchar(11))as datetime 

Para obter AAAA-MM-DD, use:

 select convert(varchar(10), getdate(), 120) 

Edit: Ops, ele quer um DateTime em vez de uma string. O equivalente de TRUNC () no Oracle. Você pode pegar o que eu postei e enviar de volta para um DateTime:

 select convert(datetime, convert(varchar(10), getdate(), 120) , 120) 

CONVERT, FLOOR e DATEDIFF serão executados da mesma forma.

Como retornar a parte de data somente de um tipo de dados de data e hora do SQL Server

Três methods descritos no link abaixo. Eu não testei o desempenho deles para determinar qual é o mais rápido.

http://www.blackwasp.co.uk/SQLDateFromDateTime.aspx

CAST(FLOOR(CAST(yourdate AS DECIMAL(12, 5))) AS DATETIME) realiza o melhor de longe. você pode ver a prova e testes ao obter a data sem tempo no sql server

E sobre SELECT CAST(CASt(GETDATE() AS int) AS DATETIME) ??

 CONVERT(VARCHAR(10), GETDATE(), 120) AS [YYYY-MM-DD]