DATEDIFF (Transact-SQL)
Возвращает количество пересеченных границ (целое число со знаком), указанных аргументом datepart, за период времени, указанный аргументами startdate и enddate.
Общие сведения обо всех типах данных и функциях даты и времени в языке Transact-SQL см. в разделе Типы данных и функции даты и времени (Transact-SQL).
Применимо для следующих объектов: SQL Server (SQL Server 2008 по текущую версию), База данных SQL Windows Azure (С первоначального выпуска по текущий выпуск). |
Синтаксические обозначения в Transact-SQL
Синтаксис
DATEDIFF ( datepart , startdate , enddate )
Аргументы
datepart
Часть аргументов startdate и enddate, которая задает тип пересекаемых границ. В следующей таблице перечислены все допустимые аргументы datepart. Эквивалентные переменные, определяемые пользователем, являются недопустимыми.datepart
Сокращения
year
yy, yyyy
quarter
qq, q
month
mm, m
dayofyear
dy, y
day
dd, d
week
wk, ww
hour
hh
minute
mi, n
second
ss, s
millisecond
ms
microsecond
mcs
nanosecond
ns
startdate
Выражение, которое можно привести к значению типа time, date, smalldatetime, datetime, datetime2 или datetimeoffset. Аргумент date может быть выражением, выражением столбца, определяемой пользователем переменной или строковым литералом. Вычитает объект startdate из объекта enddateВо избежание неоднозначности используйте четырехзначную запись года. Сведения об обозначении года двумя цифрами см. в разделе Настройка параметра конфигурации сервера two digit year cutoff.
enddate
См. раздел startdate.
Возвращаемый тип
int
Возвращаемое значение
- Каждое выражение datepart и его краткие формы возвращают одно и то же значение.
Если возвращенное значение выходит за границы диапазона значений типа int (от -2 147 483 648 до +2 147 483 647), возвращается ошибка. Для единицы измерения millisecond максимальная разница между значениями startdate и enddate составляет 24 дня, 20 часов, 31 минута и 23,647 секунды. Для единицы измерения second максимальная разница составляет 68 лет.
Если обоим аргументам startdate и enddate присвоено только значение времени, а аргумент datepart не содержит значения времени, то возвращается значение 0.
При вычислении возвращаемого значения смещение часовых поясов для аргументов startdate и endate не учитывается.
Так как значение типа smalldatetime имеет точность до минуты, то при использовании в аргументах startdate и enddate значения типа smalldatetime секунды и миллисекунды всегда равны 0.
Если переменной типа данных date присвоено только значение времени, в качестве недостающей части даты используется значение по умолчанию: 1900-01-01. Если переменой типа данных time или date присвоено только значение времени, в качестве недостающей части времени используется значение по умолчанию: 00:00:00. Если в одном из аргументов startdate и enddate указано только время, а в другом только дата, в качестве недостающей информации используются значения по умолчанию.
Если аргументы startdate и enddate имеют разные типы данных даты, но при этом один из них имеет больше частей времени или обладает более высокой точностью, значениям недостающих частей другого аргумента присваиваются значения 0.
Границы, указываемые аргументом datepart
Следующие инструкции имеют одинаковые значения аргументов startdate и endate. Указанные даты являются соседними, а временная разница между ними составляет 0,0000001 секунды. Разница между аргументами startdate и endate в каждой инструкции пересекает одну календарную или временную границу аргумента datepart. Каждое выражение возвращает значение 1. Если в данном примере в аргументах startdate и endate указаны различные года и при этом указанные границы находятся в пределах одной календарной недели, то для значения week будет возвращено значение 0.
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(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');
Замечания
Функция DATEDIFF может использоваться в предложениях WHERE, HAVING, GROUP BY и ORDER BY, а также при составлении списка выбора.
Функция DATEDIFF неявно приводит строковые литералы к типу datetime2. Это означает, что при передаче даты в виде строки DATEDIFF не поддерживает формат ГЧМ (год, число, месяц). Для использования формата ГЧМ (год, число, месяц) необходимо явно привести строку к типу datetime или smalldatetime.
Указание SET DATEFIRST не влияет на DATEDIFF. DATEDIFF всегда считает воскресенье первым днем недели, чтобы обеспечить детерминистичность работы функции.
Примеры
В следующих примерах выражения различного типа используются в качестве аргументов для параметров 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;
-- Returns: 1
Б.Указание определенных пользователем переменных в качестве начальной и конечной даты
В следующем примере в качестве аргументов startdate и enddate выступают определенные пользователем переменные.
DECLARE @startdate datetime2 = '2007-05-05 12:10:09.3312722';
DECLARE @enddate datetime2 = '2007-05-04 12:10:09.3312722';
SELECT DATEDIFF(day, @startdate, @enddate);
В.Указание скалярных системных функций в качестве начальной и конечной даты
В следующем примере в качестве аргументов startdate и enddate используются скалярные системные функции.
SELECT DATEDIFF(millisecond, GETDATE(), SYSDATETIME());
Г.Указание скалярных вложенных запросов и скалярных функций в качестве начальной и конечной даты
В следующем примере в качестве аргументов startdate и enddate используются скалярные вложенные запросы и скалярные функции.
USE AdventureWorks2012;
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');
Е.Указание числовых выражений и скалярных системных функций в качестве конечной даты
В следующем примере в качестве аргумента enddate используются числовое выражение (GETDATE ()+ 1) и скалярные системные функции GETDATE и SYSDATETIME.
USE AdventureWorks2012;
GO
SELECT DATEDIFF(day, '2007-05-07 09:53:01.0376635', GETDATE()+ 1)
AS NumberOfDays
FROM Sales.SalesOrderHeader;
GO
USE AdventureWorks2012;
GO
SELECT DATEDIFF(day, '2007-05-07 09:53:01.0376635', DATEADD(day,1,SYSDATETIME())) AS NumberOfDays
FROM Sales.SalesOrderHeader;
GO
Ж.Указание ранжирующих функций в качестве начальной даты
В следующем примере в качестве аргумента startdate используется ранжирующая функция.
USE AdventureWorks2012;
GO
SELECT p.FirstName, p.LastName
,DATEDIFF(day,ROW_NUMBER() OVER (ORDER BY
a.PostalCode),SYSDATETIME()) AS 'Row Number'
FROM Sales.SalesPerson s
INNER JOIN Person.Person p
ON s.BusinessEntityID = p.BusinessEntityID
INNER JOIN Person.Address a
ON a.AddressID = p.BusinessEntityID
WHERE TerritoryID IS NOT NULL
AND SalesYTD <> 0;
З.Указание агрегатной оконной функции в качестве начальной даты
В следующем примере в качестве аргумента startdate используется агрегатная оконная функция.
USE AdventureWorks2012;
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 sod
INNER JOIN Sales.SalesOrderHeader soh
ON sod.SalesOrderID = soh.SalesOrderID
WHERE soh.SalesOrderID IN(43659,58918);
GO