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

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

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


Донат для форума - использовать для поднятия настроения себе и модераторам

А ещё здесь можно купить рекламу за 25 тыс руб в месяц! ) пишите сюда - alarforum@yandex.ru

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

Есть функция, считает стаж.
Но возникает вопрос, почему по отдельности два периода считает так:
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
Адрес: Северодонецк.ua
Сообщений: 18,986
Репутация: 6725
По умолчанию

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

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

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

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

Цитата:
Сообщение от 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
Репутация: 10
По умолчанию

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

Опции темы

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
расчет стажа работы 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


01:43.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2019, Jelsoft Enterprises Ltd.