Partilhar via


DATEDIFF (Transact-SQL)

Aplica-se a: SQL Server Banco de Dados SQL do Azure Instância Gerenciada de SQL do Azure Azure Synapse Analytics Analytics Platform System (PDW)

Essa função retorna a contagem (como um valor inteiro com sinal) dos limites de datepart especificados cruzados entre os parâmetros especificados startdate e enddate.

Consulte DATEDIFF_BIG para obter uma função que lida com diferenças maiores entre os valores startdate e enddate. Consulte Tipos de dados e funções de data e hora para obter uma visão geral de todos os tipos de dados e funções de data e hora do Transact-SQL.

Convenções de sintaxe de Transact-SQL

Sintaxe

DATEDIFF ( datepart , startdate , enddate )

Argumentos

datepart

Especifica as unidades nas quais DATEDIFF relata a diferença entre a data de início e a data de término. Unidades de datepart usadas com frequência incluem month ou second.

O valor datepart não pode ser especificado em uma variável, nem como uma cadeia de caracteres entre aspas como 'month'.

A tabela a seguir lista todos os valores válidos de datepart. DATEDIFF aceita o nome completo da parte da data ou qualquer abreviação listada do nome completo.

Nome do datepart Abreviação do datepart
year yy, yyyy
quarter qq, q
month mm, m
dayofyear dy, y
day dd, d
week wk, ww
weekday dw, w
hour hh
minute mi, n
second ss, s
millisecond ms
microsecond mcs
nanosecond ns

Cada nome de datepart específico e abreviações para esse nome de datepart retornam o mesmo valor.

startdate

Uma expressão que pode resolver um dos seguintes valores:

  • date
  • datetime
  • datetimeoffset
  • datetime2
  • smalldatetime
  • time

Use anos de quatro dígitos para evitar ambiguidade. Consulte Configuração do servidor: corte de ano de dois dígitos para obter informações sobre valores de ano de dois dígitos.

enddate

Consulte startdate.

Tipos de retorno

int

Valor retornado

A diferença int entre startdate e enddate expressa no limite definido por datepart.

Por exemplo, SELECT DATEDIFF(day, '2036-03-01', '2036-02-28'); retorna -2, sugerindo que 2036 deve ser um ano bissexto. Este caso significa que se começarmos em startdate 2036-03-01, e depois contarmos -2 os dias, atingimos a enddate de 2036-02-28.

Para um valor retornado fora do intervalo para int (-2.147.483.648 a +2.147.483.647), DATEDIFF retorna um erro. Para millisecond, a diferença máxima entre a data de início e a data de término é de 24 dias, 20 horas, 31 minutos e 23,647 segundos. Para second, a diferença máxima é de 68 anos, 19 dias, 3 horas, 14 minutos e 7 segundos.

Se startdate e enddate forem atribuídos apenas a um valor de hora e a datepart não for uma data de hora, DATEDIFF retornará 0.

DATEDIFF usa um componente de deslocamento de fuso horário de startdate ou enddate para calcular o valor retornado.

Como smalldatetime é preciso apenas para o minuto, segundos e milissegundos são sempre definidos como 0 no valor retornado quando startdate ou enddate têm um valor smalldatetime .

Se apenas um valor temporal for atribuído a uma variável de tipo de dados de data, DATEDIFF definirá o valor da parte de data ausente como o valor padrão: 1900-01-01. Se apenas um valor de data for atribuído a uma variável de um tipo de dados de data ou hora, DATEDIFF definirá o valor da parte de hora ausente como o valor padrão: 00:00:00. Se startdate ou enddate tiver apenas uma parte de hora e a outra apenas uma parte de data, DATEDIFF definirá as partes de hora e data ausentes como os valores padrão.

Se startdate e enddate tiverem tipos de dados de data diferentes e um tiver mais partes de tempo ou precisão de segundos fracionários do que o outro, DATEDIFF definirá as partes ausentes do outro como 0.

Limites de datepart

As instruções a seguir têm os mesmos valores de startdate e de enddate. Essas datas são adjacentes e diferem no tempo em 100 nanossegundos (0,0000001 segundo). A diferença entre startdate e enddate em cada instrução cruza um calendário ou limite de hora de sua datepart. Cada instrução retorna 1.

SELECT DATEDIFF(year, '2005-12-31 23:59:59.9999999', '2006-01-01 00:00:00.0000000');
SELECT DATEDIFF(quarter, '2005-12-31 23:59:59.9999999', '2006-01-01 00:00:00.0000000');
SELECT DATEDIFF(month, '2005-12-31 23:59:59.9999999', '2006-01-01 00:00:00.0000000');
SELECT DATEDIFF(dayofyear, '2005-12-31 23:59:59.9999999', '2006-01-01 00:00:00.0000000');
SELECT DATEDIFF(day, '2005-12-31 23:59:59.9999999', '2006-01-01 00:00:00.0000000');
SELECT DATEDIFF(week, '2005-12-31 23:59:59.9999999', '2006-01-01 00:00:00.0000000');
SELECT DATEDIFF(weekday, '2005-12-31 23:59:59.9999999', '2006-01-01 00:00:00.0000000');
SELECT DATEDIFF(hour, '2005-12-31 23:59:59.9999999', '2006-01-01 00:00:00.0000000');
SELECT DATEDIFF(minute, '2005-12-31 23:59:59.9999999', '2006-01-01 00:00:00.0000000');
SELECT DATEDIFF(second, '2005-12-31 23:59:59.9999999', '2006-01-01 00:00:00.0000000');
SELECT DATEDIFF(millisecond, '2005-12-31 23:59:59.9999999', '2006-01-01 00:00:00.0000000');
SELECT DATEDIFF(microsecond, '2005-12-31 23:59:59.9999999', '2006-01-01 00:00:00.0000000');

Se startdate e enddate tiverem valores de ano diferentes, mas tiverem os mesmos valores de semana do calendário, DATEDIFF retornará 0 para datepart week.

Comentários

Use DATEDIFF nas SELECT <list>cláusulas , WHERE, HAVING, GROUP BY, e ORDER BY .

DATEDIFF converte implicitamente literais de cadeias de caracteres como um tipo datetime2. Em outras palavras, DATEDIFF não dá suporte ao formato YDM quando a data é passada como uma cadeia de caracteres. Você deve converter explicitamente a cadeia de caracteres em um tipo datetime ou smalldatetime para usar o YDM formato.

Especificar SET DATEFIRST não tem efeito sobre DATEDIFF. DATEDIFF sempre usa domingo como o primeiro dia da semana para garantir que a função opere de maneira determinística.

DATEDIFF pode estourar com uma precisão de minute ou superior, se a diferença entre enddate e startdate retornar um valor que está fora do intervalo para int.

Exemplos

Os exemplos de código do Transact-SQL deste artigo usa o banco de dados de exemplo AdventureWorks2022 ou AdventureWorksDW2022, que pode ser baixado da home page Microsoft SQL Server Samples and Community Projects.

Esses exemplos usam diferentes tipos de expressões como argumentos para os parâmetros startdate e enddate.

R. Especificar colunas para data de início e data de término

Este exemplo calcula o número de limites de dia cruzados entre datas em duas colunas de uma tabela.

CREATE TABLE dbo.Duration
(
    startDate DATETIME2,
    endDate DATETIME2
);

INSERT INTO dbo.Duration (startDate, endDate)
VALUES ('2007-05-06 12:10:09', '2007-05-07 12:10:09');

SELECT DATEDIFF(day, startDate, endDate) AS [Duration]
FROM dbo.Duration;

Veja a seguir o conjunto de resultados.

Duration
--------
1

B. Especificar variáveis definidas pelo usuário para startdate e enddate

Nesse exemplo, variáveis definidas pelo usuário funcionam como argumentos para startdate e enddate.

DECLARE @startdate AS DATETIME2 = '2007-05-05 12:10:09.3312722';
DECLARE @enddate AS DATETIME2 = '2007-05-04 12:10:09.3312722';

SELECT DATEDIFF(day, @startdate, @enddate);

C. Especificar funções escalares do sistema para startdate e enddate

Esse exemplo usa funções do sistema escalares como argumentos para startdate e enddate.

SELECT DATEDIFF(millisecond, GETDATE(), SYSDATETIME());

D. Especificar subconsultas escalares e funções escalares para startdate e enddate

Este exemplo usa subconsultas e funções escalares como argumentos para startdate e enddate.

USE AdventureWorks2022;
GO

SELECT DATEDIFF(day, (SELECT MIN(OrderDate)
                      FROM Sales.SalesOrderHeader), (SELECT MAX(OrderDate)
                                                    FROM Sales.SalesOrderHeader));

E. Especificar constantes para startdate e enddate

Este exemplo usa constantes de caractere como argumentos para startdate e enddate.

SELECT DATEDIFF(day, '2007-05-07 09:53:01.0376635', '2007-05-08 09:53:01.0376635');

F. Especificar expressões numéricas e funções do sistema escalar para enddate

Esse exemplo usa uma expressão numérica, (GETDATE() + 1), e as funções do sistema escalares, GETDATE e SYSDATETIME, como argumentos para enddate.

USE AdventureWorks2022;
GO

SELECT DATEDIFF(day, '2007-05-07 09:53:01.0376635', GETDATE() + 1) AS NumberOfDays
FROM Sales.SalesOrderHeader;
GO

USE AdventureWorks2022;
GO

SELECT DATEDIFF(day, '2007-05-07 09:53:01.0376635', DATEADD(day, 1, SYSDATETIME())) AS NumberOfDays
FROM Sales.SalesOrderHeader;
GO

G. Especificar funções de classificação para startdate

Este exemplo usa uma função de classificação como um argumento para startdate.

USE AdventureWorks2022;
GO

SELECT p.FirstName,
       p.LastName,
       DATEDIFF(day, ROW_NUMBER() OVER (ORDER BY a.PostalCode), SYSDATETIME()) AS 'Row Number'
FROM Sales.SalesPerson AS s
     INNER JOIN Person.Person AS p
         ON s.BusinessEntityID = p.BusinessEntityID
     INNER JOIN Person.Address AS a
         ON a.AddressID = p.BusinessEntityID
WHERE TerritoryID IS NOT NULL
      AND SalesYTD <> 0;

H. Especificar uma função de janela agregada para startdate

Este exemplo usa uma função de janela de agregação como um argumento para startdate.

USE AdventureWorks2022;
GO

SELECT soh.SalesOrderID,
       sod.ProductID,
       sod.OrderQty,
       soh.OrderDate,
       DATEDIFF(day, MIN(soh.OrderDate) OVER (PARTITION BY soh.SalesOrderID), SYSDATETIME()) AS 'Total'
FROM Sales.SalesOrderDetail AS sod
     INNER JOIN Sales.SalesOrderHeader AS soh
         ON sod.SalesOrderID = soh.SalesOrderID
WHERE soh.SalesOrderID IN (43659, 58918);
GO

I. Encontre a diferença entre startdate e enddate como strings de partes de data

-- DOES NOT ACCOUNT FOR LEAP YEARS
DECLARE @date1 AS DATETIME, @date2 AS DATETIME, @result AS VARCHAR (100);

DECLARE @years AS INT, @months AS INT, @days AS INT, @hours AS INT, @minutes AS INT, @seconds AS INT, @milliseconds AS INT;

SET @date1 = '1900-01-01 00:00:00.000';

SET @date2 = '2018-12-12 07:08:01.123';

SELECT @years = DATEDIFF(yy, @date1, @date2);

IF DATEADD(yy, -@years, @date2) < @date1
    SELECT @years = @years - 1;

SET @date2 = DATEADD(yy, -@years, @date2);

SELECT @months = DATEDIFF(mm, @date1, @date2);

IF DATEADD(mm, -@months, @date2) < @date1
    SELECT @months = @months - 1;

SET @date2 = DATEADD(mm, -@months, @date2);

SELECT @days = DATEDIFF(dd, @date1, @date2);

IF DATEADD(dd, -@days, @date2) < @date1
    SELECT @days = @days - 1;

SET @date2 = DATEADD(dd, -@days, @date2);

SELECT @hours = DATEDIFF(hh, @date1, @date2);

IF DATEADD(hh, -@hours, @date2) < @date1
    SELECT @hours = @hours - 1;

SET @date2 = DATEADD(hh, -@hours, @date2);

SELECT @minutes = DATEDIFF(mi, @date1, @date2);

IF DATEADD(mi, -@minutes, @date2) < @date1
    SELECT @minutes = @minutes - 1;

SET @date2 = DATEADD(mi, -@minutes, @date2);

SELECT @seconds = DATEDIFF(s, @date1, @date2);

IF DATEADD(s, -@seconds, @date2) < @date1
    SELECT @seconds = @seconds - 1;

SET @date2 = DATEADD(s, -@seconds, @date2);

SELECT @milliseconds = DATEDIFF(ms, @date1, @date2);

SELECT @result = ISNULL(CAST (NULLIF (@years, 0) AS VARCHAR (10)) + ' years,', '')
    + ISNULL(' ' + CAST (NULLIF (@months, 0) AS VARCHAR (10)) + ' months,', '')
    + ISNULL(' ' + CAST (NULLIF (@days, 0) AS VARCHAR (10)) + ' days,', '')
    + ISNULL(' ' + CAST (NULLIF (@hours, 0) AS VARCHAR (10)) + ' hours,', '')
    + ISNULL(' ' + CAST (@minutes AS VARCHAR (10)) + ' minutes and', '')
    + ISNULL(' ' + CAST (@seconds AS VARCHAR (10)) + CASE
        WHEN @milliseconds > 0
        THEN '.' + CAST (@milliseconds AS VARCHAR (10))
        ELSE ''
    END + ' seconds', '');

SELECT @result;

Veja a seguir o conjunto de resultados.

118 years, 11 months, 11 days, 7 hours, 8 minutes and 1.123 seconds

Exemplos: Azure Synapse Analytics e PDW (Analytics Platform System)

Esses exemplos usam diferentes tipos de expressões como argumentos para os parâmetros startdate e enddate.

J. Especificar colunas para data de início e data de término

Este exemplo calcula o número de limites de dia cruzados entre datas em duas colunas de uma tabela.

CREATE TABLE dbo.Duration
(
    startDate DATETIME2,
    endDate DATETIME2
);

INSERT INTO dbo.Duration (startDate, endDate)
VALUES ('2007-05-06 12:10:09', '2007-05-07 12:10:09');

SELECT TOP (1) DATEDIFF(day, startDate, endDate) AS [Duration]
FROM dbo.Duration;
Duration
--------
1

K. Especificar subconsultas escalares e funções escalares para startdate e enddate

Este exemplo usa subconsultas e funções escalares como argumentos para startdate e enddate.

-- Uses AdventureWorks
SELECT TOP (1) DATEDIFF(day, (SELECT MIN(HireDate)
                              FROM dbo.DimEmployee), (SELECT MAX(HireDate)
                                                      FROM dbo.DimEmployee))
FROM dbo.DimEmployee;

L. Especificar constantes para startdate e enddate

Este exemplo usa constantes de caractere como argumentos para startdate e enddate.

-- Uses AdventureWorks
SELECT TOP (1) DATEDIFF(day, '2007-05-07 09:53:01.0376635', '2007-05-08 09:53:01.0376635')
FROM DimCustomer;

M. Especificar funções de classificação para startdate

Este exemplo usa uma função de classificação como um argumento para startdate.

-- Uses AdventureWorks
SELECT FirstName,
       LastName,
       DATEDIFF(day, ROW_NUMBER() OVER (ORDER BY DepartmentName), SYSDATETIME()) AS RowNumber
FROM dbo.DimEmployee;

N. Especificar uma função de janela agregada para startdate

Este exemplo usa uma função de janela de agregação como um argumento para startdate.

-- Uses AdventureWorks
SELECT FirstName,
       LastName,
       DepartmentName,
       DATEDIFF(year, MAX(HireDate) OVER (PARTITION BY DepartmentName), SYSDATETIME()) AS SomeValue
FROM dbo.DimEmployee;