Разница между двумя датами в sql server


84

Есть ли способ понять разницу между двумя datetimeв sql server?

Например, мои даты

  1. 2010-01-22 15:29:55.090
  2. 2010-01-22 15:30:09.153

Итак, результат должен быть 14.063 seconds.


3
Вы получаете все datediffответы, но ни один, кажется, не напоминает вам, что вы можете получить отрицательные результаты в зависимости от порядка параметров.
Паси Саволайнен

Ответы:


94

Просто предостережение о DateDiff: он подсчитывает количество раз, когда вы переходите границу, указанную в качестве единиц измерения, поэтому могут возникнуть проблемы, если вы ищете точный временной интервал. например

select datediff (m, '20100131', '20100201')

дает ответ 1, потому что он пересек границу с января по февраль, поэтому, даже если интервал составляет 2 дня, dateiff вернет значение 1 - он пересек 1 границу даты.

select datediff(mi, '2010-01-22 15:29:55.090' , '2010-01-22 15:30:09.153')

Дает значение 1, опять же, он прошел границу минут один раз, поэтому, даже если это примерно 14 секунд, оно будет возвращено как одна минута при использовании минут в качестве единиц.



19
SELECT  DATEDIFF(day, '2010-01-22 15:29:55.090', '2010-01-22 15:30:09.153')

Замените dayдругими единицами, в которых вы хотите получить разницу, например second, minuteи т. Д.


16

Я могу упомянуть четыре важные функции MS SQL Server, которые могут быть очень полезны:

1) Функция DATEDIFF () отвечает за вычисление разницы между двумя датами, результатом может быть « год квартал месяц день год год день неделя час минута секунда миллисекунда микросекунда наносекунда », указанная в первом параметре ( datepart ):

select datediff(day,'1997-10-07','2011-09-11')

2) Вы можете использовать функцию GETDATE (), чтобы получить фактическое время и вычислить разницу между датой и фактической датой:

select datediff(day,'1997-10-07', getdate() )

3) Еще одна важная функция - DATEADD () , используемая для преобразования некоторого значения в datetime с использованием той же части datepart dateiff , которую вы можете добавить (с положительными значениями) или вычесть (с отрицательными значениями) к одной базовой дате:

select DATEADD(day,  45, getdate()) -- actual datetime adding 45 days
select DATEADD(  s,-638, getdate()) -- actual datetime subtracting 10 minutes and 38 seconds

4) Функция CONVERT () была создана для форматирования даты, как вам нужно, это не параметрическая функция, но вы можете использовать часть результата для форматирования результата, как вам нужно:

select convert(  char(8), getdate() ,   8) -- part hh:mm:ss of actual datetime
select convert(  varchar, getdate() , 112) -- yyyymmdd
select convert( char(10), getdate() ,  20) -- yyyy-mm-dd limited by 10 characters

DATETIME может быть рассчитано в секундах, и один интересный результат смешивания этих четырех функций состоит в том, чтобы показать сформированную разницу в часах, минутах и ​​секундах ( чч: мм: сс ) между двумя датами:

declare  @date1 datetime, @date2 datetime
set @date1=DATEADD(s,-638,getdate())
set @date2=GETDATE()

select convert(char(8),dateadd(s,datediff(s,@date1,@date2),'1900-1-1'),8)

... результат 00:10:38 (638 с = 600 с + 38 с = 10 минут и 38 секунд)

Другой пример:

select distinct convert(char(8),dateadd(s,datediff(s, CRDATE , GETDATE() ),'1900-1-1'),8) from sysobjects order by 1

9

Я пробовал этот способ, и это сработало. Я использовал SQL Server версии 2016

SELECT DATEDIFF(MILLISECOND,'2010-01-22 15:29:55.090', '2010-01-22 15:30:09.153')/1000.00;

Различные функции DATEDIFF:

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

Ссылка: https://docs.microsoft.com/en-us/sql/t-sql/functions/datediff-transact-sql?view=sql-server-2017


7

Хорошо, мы все знаем, что ответ включает DATEDIFF(). Но это дает вам только половину того результата, который вы можете получить. Что, если вы хотите получить результаты в удобочитаемом формате, выраженном в минутах и ​​секундах между двумя DATETIMEзначениями?

Функции CONVERT(), DATEADD()и, конечно DATEDIFF()же, идеально подходят для более удобочитаемого результата, который могут использовать ваши клиенты вместо числа.

т.е.

CONVERT(varchar(5), DATEADD(minute, DATEDIFF(MINUTE, date1, date2), 0), 114) 

Это даст вам что-то вроде:

ЧЧ: ММ

Если вы хотите большей точности, просто увеличьте VARCHAR().

CONVERT(varchar(12), DATEADD(minute, DATEDIFF(MINUTE, date1, date2), 0), 114) 

ЧЧ: ММ.СС.МС


5

На внутреннем уровне в SQL Server даты хранятся как 2 целых числа. Первое целое число - это количество дат до или после базовой даты (1900/01/01). Второе целое число хранит количество тактов часов после полуночи, каждый такт составляет 1/300 секунды.

Больше информации здесь

Из-за этого я часто нахожу самый простой способ сравнить даты - просто вычесть их. Это обрабатывает 90% моих вариантов использования. Например,

select date1, date2, date2 - date1 as DifferenceInDays
from MyTable
...

Когда мне нужен ответ в единицах, отличных от дней, я буду использовать DateDiff .


6
Обратите внимание , что это относится только к старому DATETIMEтипу, а не DATE, TIMEили DATETIME2. Кроме того, возвращаемое значение будет другим DATETIME, поэтому вам нужно будет преобразовать его, чтобы получить удобочитаемое количество дней между датами.

5

Есть несколько способов увидеть разницу в датах и ​​многое другое при сравнении даты и времени. Вот что я использую, чтобы увидеть разницу между двумя датами, отформатированными как «ЧЧ: ММ: СС»:

ElapsedTime AS
      RIGHT('0' + CAST(DATEDIFF(S, StartDate, EndDate)        / 3600 AS VARCHAR(2)), 2) + ':'
    + RIGHT('0' + CAST(DATEDIFF(S, StartDate, EndDate) % 3600 /   60 AS VARCHAR(2)), 2) + ':'
    + RIGHT('0' + CAST(DATEDIFF(S, StartDate, EndDate) %   60        AS VARCHAR(2)), 2)

Я использовал это для вычисляемого столбца, но вы можете тривиально переписать его как UDF или вычисление запроса. Обратите внимание, что эта логика округляет доли секунды в меньшую сторону; 00: 00.00 - 00: 00.999 считается нулевой секунд и отображается как «00:00:00».

Если вы ожидаете, что периоды могут длиться более нескольких дней, этот код при необходимости переключается на формат D: HH: MM: SS:

ElapsedTime AS
    CASE WHEN DATEDIFF(S, StartDate, EndDate) >= 359999
        THEN
                          CAST(DATEDIFF(S, StartDate, EndDate) / 86400        AS VARCHAR(7)) + ':'
            + RIGHT('0' + CAST(DATEDIFF(S, StartDate, EndDate) % 86400 / 3600 AS VARCHAR(2)), 2) + ':'
            + RIGHT('0' + CAST(DATEDIFF(S, StartDate, EndDate) %  3600 /   60 AS VARCHAR(2)), 2) + ':'
            + RIGHT('0' + CAST(DATEDIFF(S, StartDate, EndDate) %    60        AS VARCHAR(2)), 2)
        ELSE
              RIGHT('0' + CAST(DATEDIFF(S, StartDate, EndDate)        / 3600 AS VARCHAR(2)), 2) + ':'
            + RIGHT('0' + CAST(DATEDIFF(S, StartDate, EndDate) % 3600 /   60 AS VARCHAR(2)), 2) + ':'
            + RIGHT('0' + CAST(DATEDIFF(S, StartDate, EndDate) %   60        AS VARCHAR(2)), 2)
        END


3
SELECT DATEDIFF(yyyy, '2011/08/25', '2017/08/25') AS DateDiff

Это дает вам разницу между двумя датами в году

Здесь (2017-2011) = 6 в результате

Синтаксис:

DATEDIFF(interval, date1, date2)

2

Используйте это для DD:MM:SS:

SELECT CONVERT(VARCHAR(max), Datediff(dd, '2019-08-14 03:16:51.360', 
         '2019-08-15 05:45:37.610')) 
       + ':' 
       + CONVERT(CHAR(8), Dateadd(s, Datediff(s, '2019-08-14 03:16:51.360', 
         '2019-08-15 05:45:37.610'), '1900-1-1'), 8) 

1

Так что это не мой ответ, но я только что нашел его, когда искал в Интернете такой вопрос. Этот парень создал процедуру для расчета часов, минут и секунд. Ссылка и код:

--Creating Function
If OBJECT_ID('UFN_HourMinuteSecond') Is Not Null
Drop Function dbo.UFN_HourMinuteSecond
Go
Exec(
'Create Function dbo.UFN_HourMinuteSecond
(
@StartDateTime DateTime,
@EndDateTime DateTime
) Returns Varchar(10) 
As
Begin

Declare @Seconds Int,
@Minute Int,
@Hour Int,
@Elapsed Varchar(10)

Select @Seconds = ABS(DateDiff(SECOND ,@StartDateTime,@EndDateTime))

If @Seconds >= 60 
Begin
select @Minute = @Seconds/60
select @Seconds = @Seconds%60

If @Minute >= 60
begin
select @hour = @Minute/60
select @Minute = @Minute%60
end

Else
Goto Final 
End

Final:
Select @Hour = Isnull(@Hour,0), @Minute = IsNull(@Minute,0), @Seconds =               IsNull(@Seconds,0)
select @Elapsed = Cast(@Hour as Varchar) + '':'' + Cast(@Minute as Varchar) + '':'' +     Cast(@Seconds as Varchar)

Return (@Elapsed)
End'
)

1
declare @dt1 datetime='2012/06/13 08:11:12', @dt2 datetime='2012/06/12 02:11:12'

select CAST((@dt2-@dt1) as time(0))


1
select
datediff(millisecond,'2010-01-22 15:29:55.090','2010-01-22 15:30:09.153') / 1000.0 as Secs

result:
Secs
14.063

Просто подумал, что упомяну об этом.


1

СОЗДАТЬ ФУНКЦИЮ getDateDiffHours (@fdate AS datetime, @ tdate as datetime) ВОЗВРАЩАЕТ varchar (50) КАК НАЧАТЬ ЗАЯВИТЬ @cnt int DECLARE @cntDate datetime DECLARE @dayDiff int DECLARE @dayDiffWk int DECLARE @hrsDECLARE @hrsDECLARE @hrs

DECLARE @markerFDate datetime
DECLARE @markerTDate datetime

DECLARE @fTime int
DECLARE @tTime int 


DECLARE @nfTime varchar(8)
DECLARE @ntTime varchar(8)

DECLARE @nfdate datetime
DECLARE @ntdate datetime

-------------------------------------
--DECLARE @fdate datetime
--DECLARE @tdate datetime

--SET @fdate = '2005-04-18 00:00:00.000'
--SET @tdate = '2005-08-26 15:06:07.030'
-------------------------------------

DECLARE @tempdate datetime

--setting weekends
SET @fdate = dbo.getVDate(@fdate)
SET @tdate = dbo.getVDate(@tdate)
--RETURN @fdate 

SET @fTime = datepart(hh,@fdate)
SET @tTime = datepart(hh,@tdate)
--RETURN @fTime 
if datediff(hour,@fdate, @tdate) <= 9

        RETURN(convert(varchar(50),0) + ' Days ' + convert(varchar(50),datediff(hour,@fdate, @tdate)))  + ' Hours'
else
--setting working hours
SET @nfTime = dbo.getV00(convert(varchar(2),datepart(hh,@fdate))) + ':' +dbo.getV00(convert(varchar(2),datepart(mi,@fdate))) + ':'+  dbo.getV00(convert(varchar(2),datepart(ss,@fdate)))
SET @ntTime = dbo.getV00(convert(varchar(2),datepart(hh,@tdate))) + ':' +dbo.getV00(convert(varchar(2),datepart(mi,@tdate))) + ':'+  dbo.getV00(convert(varchar(2),datepart(ss,@tdate)))

IF @fTime > 17 
begin
    set @nfTime = '17:00:00'
end 
else
begin
    IF @fTime < 8 
        set @nfTime = '08:00:00'
end 

IF @tTime > 17 
begin
    set @ntTime = '17:00:00'
end 
else
begin
    IF @tTime < 8 
        set @ntTime = '08:00:00'
end 



-- used for working out whole days

SET @nfdate = dateadd(day,1,@fdate) 

SET @ntdate = @tdate
SET @nfdate = convert(varchar,datepart(yyyy,@nfdate)) + '-' + convert(varchar,datepart(mm,@nfdate)) + '-' + convert(varchar,datepart(dd,@nfdate))
SET @ntdate = convert(varchar,datepart(yyyy,@ntdate)) + '-' + convert(varchar,datepart(mm,@ntdate)) + '-' + convert(varchar,datepart(dd,@ntdate))
SET @cnt = 0
SET @dayDiff = 0 
SET @cntDate = @nfdate
SET @dayDiffWk = convert(decimal(18,2),@ntdate-@nfdate)

--select @nfdate,@ntdate

WHILE @cnt < @dayDiffWk
BEGIN   
    IF (NOT DATENAME(dw, @cntDate) = 'Saturday') AND (NOT DATENAME(dw, @cntDate) = 'Sunday')
    BEGIN 
        SET @dayDiff = @dayDiff + 1
    END 
    SET @cntDate = dateadd(day,1,@cntDate)
    SET @cnt = @cnt + 1
END 

--SET @dayDiff = convert(decimal(18,2),@ntdate-@nfdate) --datediff(day,@nfdate,@ntdate)
--SELECT @dayDiff

set @fdate = convert(varchar,datepart(yyyy,@fdate)) + '-' + convert(varchar,datepart(mm,@fdate)) + '-' + convert(varchar,datepart(dd,@fdate)) + ' ' + @nfTime
set @tdate = convert(varchar,datepart(yyyy,@tdate)) + '-' + convert(varchar,datepart(mm,@tdate)) + '-' + convert(varchar,datepart(dd,@tdate)) + ' ' + @ntTime

set @markerFDate = convert(varchar,datepart(yyyy,@fdate)) + '-' + convert(varchar,datepart(mm,@fdate)) + '-' + convert(varchar,datepart(dd,@fdate)) + ' ' + '17:00:00'
set @markerTDate = convert(varchar,datepart(yyyy,@tdate)) + '-' + convert(varchar,datepart(mm,@tdate)) + '-' + convert(varchar,datepart(dd,@tdate)) + ' ' + '08:00:00'

--select @fdate,@tdate
--select @markerFDate,@markerTDate

set @hrsDiff = convert(decimal(18,2),datediff(hh,@fdate,@markerFDate))

--select @hrsDiff
set @hrsDiff = @hrsDiff +  convert(int,datediff(hh,@markerTDate,@tdate))

--select @fdate,@tdate  

IF convert(varchar,datepart(yyyy,@fdate)) + '-' + convert(varchar,datepart(mm,@fdate)) + '-' + convert(varchar,datepart(dd,@fdate)) = convert(varchar,datepart(yyyy,@tdate)) + '-' + convert(varchar,datepart(mm,@tdate)) + '-' + convert(varchar,datepart(dd,@tdate))  
BEGIN
    --SET @hrsDiff = @hrsDiff - 9
    Set @hrsdiff = datediff(hour,@fdate,@tdate)
END 

--select FLOOR((@hrsDiff / 9))

IF (@hrsDiff / 9) > 0 
BEGIN
    SET @dayDiff = @dayDiff + FLOOR(@hrsDiff / 9)
    SET @hrsDiff = @hrsDiff - FLOOR(@hrsDiff / 9)*9
END 

--select convert(varchar(50),@dayDiff) + ' Days ' + convert(varchar(50),@hrsDiff)   + ' Hours'

RETURN(convert(varchar(50),@dayDiff) + ' Days ' + convert(varchar(50),@hrsDiff))    + ' Hours'

КОНЕЦ


1
Можете ли вы объяснить свой код в соответствии с вопросом?
user7294900

1

Сол-1:

select 
  StartTime
  , EndTime
  , CONVERT(NVARCHAR,(EndTime-StartTime), 108) as TimeDiff 
from 
  [YourTable]

Сол-2:

select 
  StartTime
  , EndTime
  , DATEDIFF(hh, StartTime, EndTime)
  , DATEDIFF(mi, StartTime, EndTime) % 60 
from 
  [YourTable]

Сол-3:

select 
  DATEPART(hour,[EndTime]-[StartTime])
  , DATEPART(minute,[EndTime]-[StartTime]) 
from 
  [YourTable]

Datepart работает лучше всего


1

Пожалуйста, проверьте трюк ниже, чтобы найти разницу в датах между двумя датами

 DATEDIFF(DAY,ordr.DocDate,RDR1.U_ProgDate) datedifff

где вы можете изменить в соответствии с вашими требованиями, так как вы хотите разницу в днях, месяцах, годах или времени.


0

Для меня это сработало идеально Convert (varchar (8), DATEADD (SECOND, DATEDIFF (SECOND, LogInTime, LogOutTime), 0), 114)

и вывод - ЧЧ: ММ: СС, который в моем случае показан точно.


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.