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
в предложениях , и WHERE
ORDER BY
GROUP BY
HAVING
предложениях.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;