Skip to content

Latest commit

 

History

History
433 lines (306 loc) · 15.3 KB

datediff-transact-sql.md

File metadata and controls

433 lines (306 loc) · 15.3 KB
titledescriptionauthorms.authorms.reviewerms.datems.servicems.subservicems.topicf1_keywordshelpviewer_keywordsdev_langsmonikerRange
DATEDIFF (Transact-SQL)
Transact-SQL reference for the DATEDIFF function. Returns the numerical difference between a start and end date based on datepart.
markingmyname
maghan
randolphwest
10/26/2024
sql
t-sql
reference
DATEDIFF_TSQL
DATEDIFF
dates [SQL Server], functions
DATEDIFF function [SQL Server]
time [SQL Server], crossed boundaries
differences in date and time [SQL Server]
counting crossed date time boundaries [SQL Server]
date and time [SQL Server], DATEDIFF
dates [SQL Server], crossed boundaries
boundary differences date and time [SQL Server]
functions [SQL Server], time
functions [SQL Server], date and time
interval dates [SQL Server]
time [SQL Server], functions
crossing date time boundaries [SQL Server]
calculating dates times [SQL Server]
TSQL
>=aps-pdw-2016 || =azuresqldb-current || =azure-sqldw-latest || >=sql-server-2016 || >=sql-server-linux-2017 || =azuresqldb-mi-current

DATEDIFF (Transact-SQL)

[!INCLUDE sql-asdb-asdbmi-asa-pdw]

This function returns the count (as a signed integer value) of the specified datepart boundaries crossed between the specified startdate and enddate.

See DATEDIFF_BIG for a function that handles larger differences between the startdate and enddate values. See Date and time data types and functions for an overview of all [!INCLUDE tsql] date and time data types and functions.

:::image type="icon" source="../../includes/media/topic-link-icon.svg" border="false"::: Transact-SQL syntax conventions

Syntax

DATEDIFF ( datepart , startdate , enddate ) 

Arguments

datepart

Specifies the units in which DATEDIFF reports the difference between the startdate and enddate. Commonly used datepart units include month or second.

The datepart value can't be specified in a variable, nor as a quoted string like 'month'.

The following table lists all the valid datepart values. DATEDIFF accepts either the full name of the datepart, or any listed abbreviation of the full name.

datepart namedatepart abbreviation
yearyy, yyyy
quarterqq, q
monthmm, m
dayofyeardy, y
daydd, d
weekwk, ww
weekdaydw, w
hourhh
minutemi, n
secondss, s
millisecondms
microsecondmcs
nanosecondns

Each specific datepart name and abbreviations for that datepart name returns the same value.

startdate

An expression that can resolve to one of the following values:

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

Use four-digit years to avoid ambiguity. See Server configuration: two digit year cutoff for information about two-digit year values.

enddate

See startdate.

Return types

int

Return value

The int difference between the startdate and enddate, expressed in the boundary set by datepart.

For example, SELECT DATEDIFF(day, '2036-03-01', '2036-02-28'); returns -2, hinting that 2036 must be a leap year. This case means that if we start at startdate2036-03-01, and then count -2 days, we reach the enddate of 2036-02-28.

For a return value out of range for int (-2,147,483,648 to +2,147,483,647), DATEDIFF returns an error. For millisecond, the maximum difference between startdate and enddate is 24 days, 20 hours, 31 minutes, and 23.647 seconds. For second, the maximum difference is 68 years, 19 days, 3 hours, 14 minutes, and 7 seconds.

If startdate and enddate are both assigned only a time value, and the datepart isn't a time datepart, DATEDIFF returns 0.

DATEDIFF uses the time zone offset component of startdate or enddate to calculate the return value.

Because smalldatetime is accurate only to the minute, seconds and milliseconds are always set to 0 in the return value when startdate or enddate have a smalldatetime value.

If only a time value is assigned to a date data type variable, DATEDIFF sets the value of the missing date part to the default value: 1900-01-01. If only a date value is assigned to a variable of a time or date data type, DATEDIFF sets the value of the missing time part to the default value: 00:00:00. If either startdate or enddate have only a time part and the other only a date part, DATEDIFF sets the missing time and date parts to the default values.

If startdate and enddate have different date data types, and one has more time parts or fractional seconds precision than the other, DATEDIFF sets the missing parts of the other to 0.

datepart boundaries

The following statements have the same startdate and the same enddate values. Those dates are adjacent and they differ in time by a hundred nanoseconds (.0000001 second). The difference between the startdate and enddate in each statement crosses one calendar or time boundary of its datepart. Each statement returns 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');

If startdate and enddate have different year values, but they have the same calendar week values, DATEDIFF returns 0 for datepartweek.

Remarks

Use DATEDIFF in the SELECT <list>, WHERE, HAVING, GROUP BY, and ORDER BY clauses.

DATEDIFF implicitly casts string literals as a datetime2 type. In other words, DATEDIFF doesn't support the format YDM when the date is passed as a string. You must explicitly cast the string to a datetime or smalldatetime type to use the YDM format.

Specifying SET DATEFIRST has no effect on DATEDIFF. DATEDIFF always uses Sunday as the first day of the week to ensure the function operates in a deterministic way.

DATEDIFF might overflow with a precision of minute or higher, if the difference between enddate and startdate returns a value that is out of range for int.

Examples

[!INCLUDE article-uses-adventureworks]

These examples use different types of expressions as arguments for the startdate and enddate parameters.

A. Specify columns for startdate and enddate

This example calculates the number of day boundaries crossed between dates in two columns in a table.

CREATETABLEdbo.Duration ( startDate DATETIME2, endDate DATETIME2 ); INSERT INTOdbo.Duration (startDate, endDate) VALUES ('2007-05-06 12:10:09', '2007-05-07 12:10:09'); SELECT DATEDIFF(day, startDate, endDate) AS [Duration] FROMdbo.Duration;

[!INCLUDE ssresult-md]

Duration -------- 1 

B. Specify user-defined variables for startdate and enddate

In this example, user-defined variables serve as arguments for startdate and 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. Specify scalar system functions for startdate and enddate

This example uses scalar system functions as arguments for startdate and enddate.

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

D. Specify scalar subqueries and scalar functions for startdate and enddate

This example uses scalar subqueries and scalar functions as arguments for startdate and enddate.

USE AdventureWorks2022; GO SELECT DATEDIFF(day, (SELECTMIN(OrderDate) FROMSales.SalesOrderHeader), (SELECTMAX(OrderDate) FROMSales.SalesOrderHeader));

E. Specify constants for startdate and enddate

This example uses character constants as arguments for startdate and enddate.

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

F. Specify numeric expressions and scalar system functions for enddate

This example uses a numeric expression, (GETDATE() + 1), and scalar system functions GETDATE and SYSDATETIME, as arguments for enddate.

USE AdventureWorks2022; GO SELECT DATEDIFF(day, '2007-05-07 09:53:01.0376635', GETDATE() +1) AS NumberOfDays FROMSales.SalesOrderHeader; GO USE AdventureWorks2022; GO SELECT DATEDIFF(day, '2007-05-07 09:53:01.0376635', DATEADD(day, 1, SYSDATETIME())) AS NumberOfDays FROMSales.SalesOrderHeader; GO

G. Specify ranking functions for startdate

This example uses a ranking function as an argument for startdate.

USE AdventureWorks2022; GO SELECTp.FirstName, p.LastName, DATEDIFF(day, ROW_NUMBER() OVER (ORDER BYa.PostalCode), SYSDATETIME()) AS'Row Number'FROMSales.SalesPersonAS s INNER JOINPerson.PersonAS p ONs.BusinessEntityID=p.BusinessEntityIDINNER JOINPerson.AddressAS a ONa.AddressID=p.BusinessEntityIDWHERE TerritoryID IS NOT NULLAND SalesYTD <>0;

H. Specify an aggregate window function for startdate

This example uses an aggregate window function as an argument for startdate.

USE AdventureWorks2022; GO SELECTsoh.SalesOrderID, sod.ProductID, sod.OrderQty, soh.OrderDate, DATEDIFF(day, MIN(soh.OrderDate) OVER (PARTITION BY soh.SalesOrderID), SYSDATETIME()) AS'Total'FROMSales.SalesOrderDetailAS sod INNER JOINSales.SalesOrderHeaderAS soh ONsod.SalesOrderID=soh.SalesOrderIDWHEREsoh.SalesOrderIDIN (43659, 58918); GO

I. Find difference between startdate and enddate as date parts strings

-- DOES NOT ACCOUNT FOR LEAP YEARS DECLARE @date1 AS DATETIME, @date2 AS DATETIME, @result ASVARCHAR (100); DECLARE @years ASINT, @months ASINT, @days ASINT, @hours ASINT, @minutes ASINT, @seconds ASINT, @milliseconds ASINT; 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) ASVARCHAR (10)) +' years,', '') + ISNULL(''+ CAST (NULLIF (@months, 0) ASVARCHAR (10)) +' months,', '') + ISNULL(''+ CAST (NULLIF (@days, 0) ASVARCHAR (10)) +' days,', '') + ISNULL(''+ CAST (NULLIF (@hours, 0) ASVARCHAR (10)) +' hours,', '') + ISNULL(''+ CAST (@minutes ASVARCHAR (10)) +' minutes and', '') + ISNULL(''+ CAST (@seconds ASVARCHAR (10)) + CASE WHEN @milliseconds >0 THEN '.'+ CAST (@milliseconds ASVARCHAR (10)) ELSE '' END +' seconds', ''); SELECT @result;

[!INCLUDE ssResult]

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

Examples: [!INCLUDE ssazuresynapse-md] and [!INCLUDE ssPDW]

These examples use different types of expressions as arguments for the startdate and enddate parameters.

J. Specify columns for startdate and enddate

This example calculates the number of day boundaries crossed between dates in two columns in a table.

CREATETABLEdbo.Duration ( startDate DATETIME2, endDate DATETIME2 ); INSERT INTOdbo.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] FROMdbo.Duration;
Duration -------- 1 

K. Specify scalar subqueries and scalar functions for startdate and enddate

This example uses scalar subqueries and scalar functions as arguments for startdate and enddate.

-- Uses AdventureWorksSELECT TOP (1) DATEDIFF(day, (SELECTMIN(HireDate) FROMdbo.DimEmployee), (SELECTMAX(HireDate) FROMdbo.DimEmployee)) FROMdbo.DimEmployee;

L. Specify constants for startdate and enddate

This example uses character constants as arguments for startdate and enddate.

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

M. Specify ranking functions for startdate

This example uses a ranking function as an argument for startdate.

-- Uses AdventureWorksSELECT FirstName, LastName, DATEDIFF(day, ROW_NUMBER() OVER (ORDER BY DepartmentName), SYSDATETIME()) AS RowNumber FROMdbo.DimEmployee;

N. Specify an aggregate window function for startdate

This example uses an aggregate window function as an argument for startdate.

-- Uses AdventureWorksSELECT FirstName, LastName, DepartmentName, DATEDIFF(year, MAX(HireDate) OVER (PARTITION BY DepartmentName), SYSDATETIME()) AS SomeValue FROMdbo.DimEmployee;

Related content

close