Форум программистов
 
О проблемах, например, с регистрацией пишите сюда - alarforum@yandex.ru, проверяйте папку спам! Обязательно пройдите активизацию e-mail, а тут можно восстановить пароль.

Вернуться   Форум программистов > Web > SQL, базы данных
Регистрация

Восстановить пароль
Повторная активизация e-mail

Здесь нужно купить рекламу за 20 тыс руб в месяц! ) пишите сюда - alarforum@yandex.ru
Без учёта ботов - 20000 человек в день, 350000 в месяц.

Ответ
 
Опции темы
Старый 21.08.2019, 13:13   #1
nactyx
Форумчанин
 
Регистрация: 11.10.2010
Сообщений: 151
По умолчанию Функция расчета стажа

Есть функция, считает стаж.
Но возникает вопрос, почему по отдельности два периода считает так:
24.05.1988 - 11.08.1988 = 0 лет 2 мес 19 дн
12.08.1988 - 12.07.1994 = 5 лет 11 мес 1 дн
В "уме" если сложить получим 6 лет 1 мес 20 дн
Но если объединить периоды и к ним применить функцию, то получим:
24.05.1988 - 12.07.1994 = 6 лет 1 мес 19 дн
Почему?
P.S. @stag_coeff_ принимать за 0 на входе, @ftime = 'P'

Код функции:
Код:
-- Функция расчета стажа по периоду между датами (день/месяц/год).
-- @ftime - флаг, указывающий возвращаемую часть стажа
-- 		"Y" - лет, "M" - месяцев, "D" - дней
--		"S" - период в формате YYY-MM-DD
--		"P" - период в формате лет:YYY мес:MM дн:DD (без лидирующих нулей)

ALTER FUNCTION [dbo].[pr_fn_calc_staj]
(
	@dd1 			DATETIME,
	@dd2 			DATETIME,
	@stag_coeff_  	NUMERIC(19,4) = 1,
	@ftime 			CHAR
)
RETURNS  VARCHAR(20) AS
BEGIN
  DECLARE
	@mm_ 	INTEGER,
	@yy_ 	INTEGER,
	@dd_ 	INTEGER,
	@mm_f 	NUMERIC(19,4),
	@yy_f 	NUMERIC(19,4),
	@dd_f 	NUMERIC(19,4),
	@yy	INTEGER,
	@mm	INTEGER,
	@dd	INTEGER

if 	@dd1 <= @dd2 /* проверка на корректность переданного диапазона дат*/
begin

  SELECT @yy   =  0,
	   @mm =  0,
	   @dd   = 0

  SELECT  @dd2 =  dateadd(day, 1, @dd2)

  if isnull(@stag_coeff_, 0) = 0  SELECT @stag_coeff_ = 1
  SELECT @yy = datediff(year, @dd1, @dd2)
  SELECT @mm = datediff(month, dateadd(year, @yy, @dd1), @dd2)

  if @mm < 0
  BEGIN
	SELECT @yy = @yy - 1
	SELECT @mm = datediff(month, dateadd(year, @yy, @dd1), @dd2)
  END

  SELECT  @dd = datediff(day, dateadd(month, @mm, dateadd(year, @yy, @dd1)), @dd2)
  if @dd < 0
  BEGIN
	SELECT @mm = @mm - 1 if @mm < 0
	SELECT @mm = 11, @yy = @yy - 1
	SELECT @dd = datediff(day, dateadd(month, @mm, dateadd(year, @yy, @dd1)), @dd2)
  END

  SELECT @yy_f = Cast(@yy as NUMERIC(19,4)) * @stag_coeff_, @mm_f = Cast(@mm * @stag_coeff_ as NUMERIC(19,4)), @dd_f = Cast(@dd * @stag_coeff_ as NUMERIC(19,4))

  SELECT @dd = convert(integer,@dd_f) + (@yy_f - convert(integer, @yy_f))*365 SELECT @yy = convert(integer, @yy_f)
  SELECT @dd = @dd + (@mm_f - convert(integer, @mm_f))*30 SELECT @mm = convert(integer, @mm_f)
  SELECT @dd = convert(integer, @dd) if @dd >= 30
  SELECT @mm = @mm + (@dd-(@dd%30))/30, @dd = @dd%30

  if @mm >= 12 SELECT @yy = @yy + (@mm-(@mm%12))/12, @mm = @mm%12
  if @yy < 0 SELECT @yy = 0, @mm = 0, @dd = 0

----------------------------------------------------------
if upper(@ftime) = 'Y' 		RETURN CONVERT(VARCHAR(10),@yy)
if upper(@ftime) = 'M' 		RETURN CONVERT(VARCHAR(2),@mm)
if upper(@ftime) = 'D' 		RETURN CONVERT(VARCHAR(2),@dd)

if upper(@ftime) = 'S'
begin
	if  @yy > 999			RETURN '999-99-99'
	else					RETURN RIGHT('000'+CONVERT(VARCHAR(3), @yy),3) +'-'+ RIGHT('00'+CONVERT(VARCHAR(2), @mm),2) +'-'+ RIGHT('00'+CONVERT(VARCHAR(2), @dd),2)
end

if upper(@ftime) = 'P'
begin
	if  @yy > 999			RETURN 'лет:999 мес:99 дн:99'
	else					RETURN 'лет:' + RIGHT('   '+CONVERT(VARCHAR(3), @yy),3) +' мес:'+ RIGHT('  '+CONVERT(VARCHAR(2), @mm),2) +' дн:'+ RIGHT('  '+CONVERT(VARCHAR(2), @dd),2)
end


end
RETURN '0'

END

Последний раз редактировалось nactyx; 21.08.2019 в 13:16.
nactyx вне форума Ответить с цитированием
Старый 21.08.2019, 13:32   #2
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 19,061
По умолчанию

Потому что в году не всегда 365 дней, да и в месяце бывает не только 30 дней
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Аватар вне форума Ответить с цитированием
Старый 21.08.2019, 14:06   #3
nactyx
Форумчанин
 
Регистрация: 11.10.2010
Сообщений: 151
По умолчанию

Цитата:
Сообщение от Аватар Посмотреть сообщение
Потому что в году не всегда 365 дней, да и в месяце бывает не только 30 дней
Это не новость. Главная загвоздка в том, что периоды одинаковые. Два отдельных, идущих друг за другом в сумме дают одно. А если их "слепить" и применить к таком периоду функцию - сумма другая на один день. Почему? Понять не могу. В этом вопрос.
nactyx вне форума Ответить с цитированием
Старый 21.08.2019, 14:47   #4
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 19,061
По умолчанию

datediff(month, '20190201', '20190301') вернет 1 месяц, там разница по факту и есть месяц

datediff(day, '20190201', '20190301') вернет 28 дней, что с точки зрения функции совсем не месяц после деления нацело на 30
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Аватар вне форума Ответить с цитированием
Старый 21.08.2019, 15:58   #5
Serge_Bliznykov
Старожил
 
Регистрация: 09.01.2008
Сообщений: 26,260
По умолчанию

Цитата:
Сообщение от nactyx Посмотреть сообщение
В этом вопрос.
Попробуйте рассмотреть такую ситуацию

24.05.1988
26.05.1988
разница 2 дня

27.05.1988
31.05.1988
разница 4 дня

24.05.1988
31.05.1988
Разница 7 дней

(когда находим разницу, то конечная дата не входит в диапазон)
Serge_Bliznykov вне форума Ответить с цитированием
Старый 22.08.2019, 12:18   #6
nactyx
Форумчанин
 
Регистрация: 11.10.2010
Сообщений: 151
По умолчанию

Спасибо, разобрался.
nactyx вне форума Ответить с цитированием
Ответ

Здесь нужно купить рекламу за 20 тыс руб в месяц! ) пишите сюда - alarforum@yandex.ru
Без учёта ботов - 20000 человек в день, 350000 в месяц.

Опции темы


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
расчет стажа работы SAUUNSAPR Microsoft Office Excel 9 15.06.2016 12:51
Расчет стажа сотрудников Zet_iKs Microsoft Office Excel 13 02.04.2016 13:37
Подсчет трудового стажа Paraz1t SQL, базы данных 6 27.06.2012 11:40
Сортировка по возрастанию и убыванию стажа betirsolt БД в Delphi 3 16.11.2010 18:52
Расчет стажа работы John_chek Общие вопросы Delphi 6 13.04.2007 13:38


Проекты отопления, пеллетные котлы, бойлеры, радиаторы
интернет магазин respective.ru
Пеллетный котёл Emtas
котлы EMTAS