Поделиться через


DATEDIFF (Transact-SQL)

Применимо: SQL Server База данных SQL Azure Управляемый экземпляр SQL Azure azure Synapse Analytics Analytics Platform System (PDW)

Эта функция возвращает количество пересеченных границ (целое число со знаком), указанных в аргументе datepart, за период времени, указанный в аргументах startdate и enddate.

См . DATEDIFF_BIG функции, которая обрабатывает более крупные различия между начальными и конечными значениями. Общие сведения о всех типах и функциях данных и функций даты и времени Transact-SQL см. в разделе "Типы и функции данных даты и времени".

Соглашения о синтаксисе Transact-SQL

Синтаксис

DATEDIFF ( datepart , startdate , enddate )

Аргументы

datepart

Указывает единицы, в которых DATEDIFF сообщается о разнице между начальной и концевой. К часто используемым единицам datepart относятся month или second.

Значение datepart не может быть указано в переменной, а также в виде строки с кавычками, например 'month'.

В приведенной ниже таблице перечислены все допустимые значения datepart. DATEDIFF принимает полное имя части даты или любое указанное сокращение полного имени.

Имя datepart Сокращение 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

Каждое конкретное имя даты и аббревиаты для этого имени даты возвращает то же значение.

startdate

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

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

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

enddate

См. описание аргумента startdate.

Типы возвращаемых данных

int

Возвращаемое значение

Значение типа int, представляющее разницу между аргументами startdate и enddate в границах, определяемых аргументом datepart.

Например, возвращается -2указание на то, SELECT DATEDIFF(day, '2036-03-01', '2036-02-28'); что 2036 год должен быть високосным годом. Это означает, что если начать с начала, 2036-03-01 а затем подсчитывать -2 дни, мы достигаем окончания. 2036-02-28

В качестве возвращаемого значения вне диапазона для int (от –2 147 483 648 до 2 147 483 647) DATEDIFF возвращает сообщение об ошибке. Для millisecondэтого максимальная разница между начальным и конечным датами составляет 24 дня, 20 часов, 31 минуты и 23,647 секунды. Для second, максимальная разница составляет 68 лет, 19 дней, 3 часа, 14 минут и 7 секунд.

Если начальная и конечная части назначены только значение времени, а дата-часть не является частью даты и времени, DATEDIFF возвращается0.

При вычислении возвращаемого значения DATEDIFF использует компонент смещения часовых поясов для аргументов startdate или enddate.

Так как значение smalldatetime является точным только к минуте, секундам и миллисекундам всегда присваивается 0 значение в возвращаемом значении при запуске или концевом значении smalldatetime.

Если переменной типа данных date присвоено только значение времени, в качестве недостающей части даты DATEDIFF задает значение по умолчанию: 1900-01-01. Если переменной типа данных time или date присвоено только значение даты, в качестве недостающей части времени DATEDIFF задает значение по умолчанию: 00:00:00. Если в одном из аргументов startdate или enddate указано только время, а в другом только дата, в качестве недостающей информации DATEDIFF задает значения по умолчанию.

Если начальный и конечный типы данных имеют разные типы данных даты, а одна — несколько частей времени или точность дробных секунд, чем другая, DATEDIFF задает отсутствующие части другого0.

Границы, задаваемые аргументом datepart

Приведенные ниже инструкции имеют одинаковые значения аргументов startdate и enddate. Указанные даты являются соседними, а временная разница между ними составляет 100 наносекунд (0,0000001 секунды). Разница между аргументами startdate и enddate в каждой инструкции пересекает одну календарную или временную границу аргумента datepart. Каждая инструкция возвращает 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');

Если начальный и конечный элемент имеют разные значения года, но они имеют одинаковые значения недели календаря, DATEDIFF возвращается 0 для datepartweek.

Замечания

Используйте DATEDIFF в предложениях , и WHEREORDER BY GROUP BYHAVINGпредложениях.SELECT <list>

Функция DATEDIFF неявно приводит строковые литералы к типу datetime2. Другими словами, DATEDIFF формат не поддерживается YDM при передаче даты в виде строки. Чтобы использовать формат, необходимо явно привести строку к типу datetime или smalldatetime.YDM

Указание SET DATEFIRST не влияет на DATEDIFF. DATEDIFF всегда считает воскресенье первым днем недели, чтобы обеспечить детерминизм работы функции.

DATEDIFF Может переполнение с точностью minute или выше, если разница между концевыми и начальными значениями возвращает значение, отличное от диапазона для int.

Примеры

Примеры кода Transact-SQL в этой статье используют AdventureWorks2022 базу данных или AdventureWorksDW2022 пример базы данных, которую можно скачать с домашней страницы примеров и проектов сообщества Microsoft SQL Server.

В этих примерах выражения различного типа используются в качестве аргументов для параметров startdate и enddate.

А. Указание столбцов для начального и концевого значения

В этом примере подсчитывается количество границ дней, пересекаемых между датами в двух столбцах таблицы.

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;

Вот результирующий набор.

Duration
--------
1

B. Указание определяемых пользователем переменных для запуска и завершения

В этом примере в качестве аргументов startdate и 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. Указание скалярных системных функций для запуска и завершения

В этом примере в качестве аргументов startdate и enddate выступают скалярные системные функции.

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

D. Указание скалярных вложенных запросов и скалярных функций для запуска и завершения

В этом примере в качестве аргументов startdate и enddate выступают скалярные вложенные запросы.

USE AdventureWorks2022;
GO

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

Е. Указание констант для запуска и завершения

В этом примере в качестве аргументов startdate и enddate используются символьные константы.

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

F. Указание числовых выражений и скалярных системных функций для завершения

В этом примере в качестве аргументов для enddate используются числовое выражение (GETDATE() + 1) и скалярные системные функции GETDATE и SYSDATETIME.

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. Указание функций ранжирования для запуска

В этом примере в качестве аргумента 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. Указание функции статистического окна для запуска

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

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

Вот результирующий набор.

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

Примеры: Azure Synapse Analytics и система платформы аналитики (PDW)

В этих примерах выражения различного типа используются в качестве аргументов для параметров startdate и enddate.

J. Указание столбцов для начального и концевого значения

В этом примере подсчитывается количество границ дней, пересекаемых между датами в двух столбцах таблицы.

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. Указание скалярных вложенных запросов и скалярных функций для запуска и завершения

В этом примере в качестве аргументов startdate и enddate выступают скалярные вложенные запросы.

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

L. Указание констант для запуска и завершения

В этом примере в качестве аргументов startdate и 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. Указание функций ранжирования для запуска

В этом примере в качестве аргумента startdate. используется ранжирующая функция.

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

О. Указание функции статистического окна для запуска

В этом примере в качестве аргумента startdate используется агрегатная оконная функция.

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