kav@94 Ответов: 3

Как получить дни вместо того, чтобы получать все дни в SQL


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

select empid, cast(floor(experience / 365) as varchar) + ' years ' +
              cast(floor(experience % 365 / 30) as varchar) + ' months ' +
              cast(experience % 30 as varchar) + ' days' as experience
from (select *, datediff(DAY, doj, getdate()) as experience
      from employee) t



но мне нужны годы месяцы и дни что было сделано но вместо того чтобы получить все дни мне нужно получить только оставшиеся дни то есть от 1 до 30 или 31

Что я уже пробовал:

я попробовал приведенный выше код, который не работает

CHill60

Я вижу, что вы изменили запрос, который используете, но он по-прежнему не работает. Почему бы не попробовать решение 2-Вторая часть, которая на самом деле делает то, что вы хотите?

3 Ответов

Рейтинг:
2

Tomas Takac

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

declare @date as date = '20150106'
declare @now as date = GetDate()
declare @years as int = DATEDIFF(year, @date, @now) -- full years
declare @date2 as date = dateadd(year, @years, @date) -- date moved by # of years
declare @months as int = DATEDIFF(month, @date2, @now) -- full months since the new date
declare @date3 as date = dateadd(month, @months, @date2) -- date moved by # of months
declare @days as int = DATEDIFF(day, @date3, @now) -- full days since the new date
select @years as [Years], @months as [Months], @days as [Days]

Это делается шаг за шагом специально, чтобы вы могли следить за тем, что происходит. Например, когда я вычисляю количество лет, я перемещаю дату на тот же временной интервал и на следующем шаге использую эту измененную дату. Это может быть легко встроено, чтобы сформировать одно утверждение, но было бы чрезвычайно трудно прочитать.
Редактировать
Приведенное выше решение работает только в некоторых ситуациях. На самом деле это не работает для 1 июня 2016 года. Вот обновленная версия:
declare @date as date = '20150601'
declare @now as date = GetDate()
declare @yearOffset as int = case when month(@date) < month(@now) or (month(@date) = month(@now) and day(@date) <= day(@now)) then 0 else -1 end
declare @years as int = DATEDIFF(year, @date, @now) + @yearOffset
declare @date2 as date = dateadd(year, @years, @date)
declare @monthOffset as int = case when day(@date) <= day(@now) then 0 else -1 end
declare @months as int = DATEDIFF(month, @date2, @now) + @monthOffset
declare @date3 as date = dateadd(month, @months, @date2)
declare @days as int = DATEDIFF(day, @date3, @now)
select @years as [Years], @months as [Months], @days as [Days]


CHill60

На самом деле я получил 2 года 3 месяца и 14 дней - это потому, что дата открыта для интерпретации и потому, что DATEDIFF (year, @date, @now) возвращает результат 2017-2015 годов

Tomas Takac

Я получаю 2y 3m 14d, что, по-моему, правильно, предполагая @date=6-Jan-2015 и @now=20-Apr-2017.

CHill60

Я прочитал дату операции как 1 июня - что соответствует их ожидаемым результатам.

Tomas Takac

Я вижу, тогда это не сработает...

Tomas Takac

Я обновил решение, посмотрите.

Рейтинг:
2

Member 12635845

SELECT CAST(DATEDIFF(yy, day, GETDATE()) AS varchar(2)) + ' Years '+
       CAST(DATEDIFF(mm, DATEADD(yy, DATEDIFF(yy, day, GETDATE()), day), GETDATE()) AS varchar(2)) +' Month '+
       CAST(DATEDIFF(dd, DATEADD(mm, DATEDIFF(mm, DATEADD(yy, DATEDIFF(yy, day, GETDATE()), day), GETDATE()), DATEADD(yy, DATEDIFF(yy, day, GETDATE()), day)),  GETDATE()) AS varchar(2)) +' Days ' AS Expr1
from records;


CHill60

Результаты через 2 года -2 месяца и 19 дней

Рейтинг:
1

CHill60

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

declare @date as date = '2015-06-01'

SELECT  CAST(DATEDIFF(day, @date,GETDATE()) / 365 AS varchar) + ' Years ' + 
		CAST(CAST(DATEDIFF(day, @date, GETDATE()) % 365 / 30.5 AS int) AS varchar) + ' Months ' +
		CAST(DATEDIFF(DAY, DATEADD(MONTH, CAST(DATEDIFF(day, @date, GETDATE()) % 365 / 30.5 AS int), 
				DATEADD(YEAR, CAST(DATEDIFF(day, @date,GETDATE()) / 365 AS int), @date)), GETDATE()) AS varchar) + ' Days'
Принцип тот же, уберите количество дней из уже рассчитанных лет и месяцев, чтобы оставить оставшиеся дни.
Однако это не очень хороший подход - он предполагает, что все годы имеют 365 дней и использует "среднее" количество дней в месяце 30,5 (что лишь немного точнее, чем использование 30).
Будут конкретные даты, когда этот расчет просто ошибочен.

[EDIT] следующее дает правильный результат и должно быть точным независимо от того, когда выполняется. Это все еще так же трудно читать:
declare @start as date = '2015-Jun-01'
declare @end as Date = getdate()

select @start, CAST(DATEDIFF(MONTH, @start, @end) / 12 AS varchar) + ' Years ' + 
	CAST(DATEDIFF(MONTH, DATEADD(YEAR, DATEDIFF(MONTH, @start, @end) / 12, @start), @end) as varchar) + ' Months ' + 
	CAST(DATEDIFF(DAY, DATEADD(MONTH, DATEDIFF(MONTH, DATEADD(YEAR, DATEDIFF(MONTH, @start, @end) / 12, @start), @end), DATEADD(YEAR,DATEDIFF(MONTH, @start, @end) / 12,@start)), @end) AS varchar) + ' Days'