Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Функция расчета возраста  [new]
marvel
Member

Откуда:
Сообщений: 1066
Чтот мозг не работает)))), спит еще...а надо срочняк накотать функция которая по дате рождения будет выводить его возраст в формате:
X лет Х месяцем Х дней
20 авг 09, 10:56    [7560191]     Ответить | Цитировать Сообщить модератору
 Re: Функция расчета возраста  [new]
Гавриленко Сергей Алексеевич
Member

Откуда: Moscow
Сообщений: 36801
datediff() вам в руки.
20 авг 09, 10:57    [7560200]     Ответить | Цитировать Сообщить модератору
 Re: Функция расчета возраста  [new]
Алексей2003
Member

Откуда: Москва
Сообщений: 5645
marvel
Чтот мозг не работает)))), спит еще...а надо срочняк накотать функция которая по дате рождения будет выводить его возраст в формате:
X лет Х месяцем Х дней

ищите поиск по словам "пенсионный фонд". кучу раз обсуждалось.
20 авг 09, 11:21    [7560431]     Ответить | Цитировать Сообщить модератору
 Re: Функция расчета возраста  [new]
iap
Member

Откуда: Москва
Сообщений: 46975
Алексей2003
marvel
Чтот мозг не работает)))), спит еще...а надо срочняк накотать функция которая по дате рождения будет выводить его возраст в формате:
X лет Х месяцем Х дней

ищите поиск по словам "пенсионный фонд". кучу раз обсуждалось.
Да можно и просто по слову "возраст"
Пример найденной темы
20 авг 09, 11:26    [7560477]     Ответить | Цитировать Сообщить модератору
 Re: Функция расчета возраста  [new]
marvel
Member

Откуда:
Сообщений: 1066
в общем пришлось включить мозг:))
может кому нить пригодиться:

set dateformat dmy
declare
	@bd datetime
set @bd = '24.04.1988'


select 
	datediff(dd, @bd, getdate())/365,
	case 
		when  (month(@bd) >= month(getdate())) and (day(@bd) >= day(getdate()))
					 then 12-month(@bd) + month(getdate()) else month(getdate()) - month(@bd) end,
	case when  day(@bd) >= day(getdate()) then day(getdate()) else day(getdate()) - day(@bd) end
20 авг 09, 13:21    [7561431]     Ответить | Цитировать Сообщить модератору
 Re: Функция расчета возраста  [new]
stimpi
Member

Откуда: Киев, Украина
Сообщений: 662
marvel
datediff(dd, @bd, getdate())/365

высокосные года не учтены
20 авг 09, 13:35    [7561568]     Ответить | Цитировать Сообщить модератору
 Re: Функция расчета возраста  [new]
marvel
Member

Откуда:
Сообщений: 1066
stimpi
marvel
datediff(dd, @bd, getdate())/365

высокосные года не учтены


кстати))))
тут тогда в цикле получаеться только мона получить точное число
20 авг 09, 13:52    [7561712]     Ответить | Цитировать Сообщить модератору
 Re: Функция расчета возраста  [new]
iljy
Member

Откуда:
Сообщений: 8711
marvel,

проблема с високосными годами. Попробуйте так:

declare @date datetime, @cd datetime
select @date = '20080821', @cd = getdate()
select  datediff(year, @date, @cd) -
		 case when month(@date) * 50 + day(@date)>month(@cd) * 50 + day(@cd) then 1 else 0 end,
    (datediff(month, @date, getdate()) -
		 case when day(@date)>day(@cd) then 1 else 0 end) %12,
    datediff(day, dateadd(m,datediff(month, @date, getdate()) -
		 case when day(@date)>day(@cd) then 1 else 0 end, @date), getdate())
20 авг 09, 13:53    [7561717]     Ответить | Цитировать Сообщить модератору
 Re: Функция расчета возраста  [new]
marvel
Member

Откуда:
Сообщений: 1066
iljy
marvel,

проблема с високосными годами. Попробуйте так:

declare @date datetime, @cd datetime
select @date = '20080821', @cd = getdate()
select  datediff(year, @date, @cd) -
		 case when month(@date) * 50 + day(@date)>month(@cd) * 50 + day(@cd) then 1 else 0 end,
    (datediff(month, @date, getdate()) -
		 case when day(@date)>day(@cd) then 1 else 0 end) %12,
    datediff(day, dateadd(m,datediff(month, @date, getdate()) -
		 case when day(@date)>day(@cd) then 1 else 0 end, @date), getdate())


а вот это можете прокоментировать:
case when month(@date) * 50 + day(@date)>month(@cd) * 50 + day(@cd) then 1 else 0 end,

не понимаю просто))
20 авг 09, 14:14    [7561869]     Ответить | Цитировать Сообщить модератору
 Re: Функция расчета возраста  [new]
stimpi
Member

Откуда: Киев, Украина
Сообщений: 662
marvel,
с высокосными годами очень просто, делайте разницу по месяцам в году их ровно 12 и кол-во не зависит от высокосных годов =)
datediff(mm, @bd, getdate())/12
20 авг 09, 14:25    [7561954]     Ответить | Цитировать Сообщить модератору
 Re: Функция расчета возраста  [new]
iljy
Member

Откуда:
Сообщений: 8711
[quot marvel
а вот это можете прокоментировать:
case when month(@date) * 50 + day(@date)>month(@cd) * 50 + day(@cd) then 1 else 0 end,

не понимаю просто))[/quot]

datediff работает очень своеобразно. например
select datediff(y,'20081231' , '20090101')
даст 1 год. Чтобы этого не было, мы проверяем месяц и день, и если для первой даты они больше, чем для текущей - разницу лет уменьшаем на 1. Аналогично с днями месяца.

stimpi,
с месяцами та же проблема
20 авг 09, 15:07    [7562250]     Ответить | Цитировать Сообщить модератору
 Re: Функция расчета возраста  [new]
igorkn
Member

Откуда:
Сообщений: 9
Если в предлагаемой функции задать @date = 07.09.1949, а @cd = 07.09.2009 возвращает 60 лет 0 месяцев и -3 дня :)
4 сен 09, 16:31    [7619561]     Ответить | Цитировать Сообщить модератору
 Re: Функция расчета возраста  [new]
iljy
Member

Откуда:
Сообщений: 8711
igorkn,

замените везде getdate() на @cd, и будет вам щастье. естественно это опечатка, потому что ТС вел речь о текущей дате.
4 сен 09, 16:40    [7619644]     Ответить | Цитировать Сообщить модератору
 Re: Функция расчета возраста  [new]
igorkn
Member

Откуда:
Сообщений: 9
Пардон, не доглядел. Теперь счастлив :)
4 сен 09, 17:21    [7619971]     Ответить | Цитировать Сообщить модератору
 Re: Функция расчета возраста  [new]
Shocker.Pro
Member

Откуда: ->|<- :адуктО
Сообщений: 21502
Почитайте дискуссию тут:
https://www.sql.ru/forum/actualthread.aspx?tid=692013
4 сен 09, 21:49    [7620853]     Ответить | Цитировать Сообщить модератору
 Re: Функция расчета возраста  [new]
AndrF
Member

Откуда:
Сообщений: 2194
я как-то баловался... В общем, ниже приведена функция возвращающая возраст (он же интервал времени) в заданных и полных размерностях времени. В том числе и прописью. Пример использования - есть в конце.

Imports System 
Imports System.Data 
Imports System.Data.SqlClient 
Imports System.Data.SqlTypes 
Imports Microsoft.SqlServer.Server 

Partial Public Class UserDefinedFunctions <Microsoft.SqlServer.Server.SqlFunction()> _ 
Public Shared Function ufnGetAgo(ByVal d1 As Date, ByVal d2 As Date, _ 
					ByVal RetValue As Char, _ 
					Optional ByVal RetValues As String = "YMDHNS" _ 
				) As SqlInt32 

	Dim Years As Integer, Months As Integer, Weeks As Integer, Days As Integer, Hours As Integer, Minutes As Integer, Seconds As Integer 
	Dim dm As Date, dw As Date, dd As Date, dh As Date, dn As Date, ds As Date 

	RetValue = UCase(RetValue) 
	RetValues = UCase(RetValues) 
	If RetValues.IndexOf(RetValue) < 0 Then Return New SqlInt32() 

	If RetValues.IndexOf("Y") < 0 Then 
		dm = d1 
		If RetValue = "Y" Then Return New SqlInt32() 
	Else 
		Years = CInt(DateDiff(DateInterval.Year, d1, d2)) 
		dm = DateAdd(DateInterval.Year, Years, d1) 
		If dm > d2 Then 
			Years -= 1 
			dm = DateAdd(DateInterval.Year, Years, d1) 
		End If 
	End If 
	If RetValue = "Y" Then Return New SqlInt32(Years) 

	If RetValues.IndexOf("M") < 0 Then 
		dw = dm 
		If RetValue = "M" Then Return New SqlInt32() 
	Else 
		Months = CInt(DateDiff(DateInterval.Month, dm, d2)) 
		dw = DateAdd(DateInterval.Month, Months, dm) 
		If dw > d2 Then 
			Months -= 1 
			dw = DateAdd(DateInterval.Month, Months, dm) 
		End If 
	End If 
	If RetValue = "M" Then Return New SqlInt32(Months) 

	If RetValues.IndexOf("W") < 0 Then 
		dd = dw 
		If RetValue = "W" Then Return New SqlInt32() 
	Else 
		Weeks = CInt(DateDiff(DateInterval.Weekday, dw, d2)) 
		dd = DateAdd(DateInterval.Weekday, Weeks, dw) 
		If dd > d2 Then 
			Weeks -= 1 
			dd = DateAdd(DateInterval.Weekday, Weeks, dw) 
		End If 
	End If 
	If RetValue = "W" Then Return New SqlInt32(Weeks) 

	If RetValues.IndexOf("D") < 0 Then 
		dh = dd 
		If RetValue = "D" Then Return New SqlInt32() 
	Else 
		Days = CInt(DateDiff(DateInterval.Day, dd, d2)) 
		dh = DateAdd(DateInterval.Day, Days, dd) 
		If dh > d2 Then 
			Days -= 1 
			dh = DateAdd(DateInterval.Day, Days, dd) 
		End If 
	End If 
	If RetValue = "D" Then Return New SqlInt32(Days) 

	If RetValues.IndexOf("H") < 0 Then 
		dn = dh 
		If RetValue = "H" Then Return New SqlInt32() 
	Else 
		Hours = CInt(DateDiff(DateInterval.Hour, dh, d2)) 
		dn = DateAdd(DateInterval.Hour, Hours, dh) 
		If dn > d2 Then 
			Hours -= 1 
			dn = DateAdd(DateInterval.Hour, Hours, dh) 
		End If 
	End If 
	If RetValue = "H" Then Return New SqlInt32(Hours) 

	If RetValues.IndexOf("N") < 0 Then 
		ds = dn 
		If RetValue = "N" Then Return New SqlInt32() 
	Else 
		Minutes = CInt(DateDiff(DateInterval.Minute, dn, d2)) 
		ds = DateAdd(DateInterval.Minute, Minutes, dn) 
		If ds > d2 Then 
			Minutes -= 1 
			ds = DateAdd(DateInterval.Minute, Minutes, dn) 
		End If 
	End If 
	If RetValue = "N" Then Return New SqlInt32(Minutes) 

	If Seconds = 0 Then 
		Return New SqlInt32() 
	Else 
		Seconds = CInt(DateDiff(DateInterval.Second, ds, d2)) 
	End If 
	If RetValue = "S" Then Return New SqlInt32(Minutes) 
End Function 

<Microsoft.SqlServer.Server.SqlFunction()> _ 
Public Shared Function ufnGetAgoString(ByVal d1 As Date, ByVal d2 As Date, _ 
						Optional ByVal RetValues As String = "YMDHNS" _ 
					) As SqlString 

	Const sr As String = ", " 
	Dim Years As Integer, Months As Integer, Weeks As Integer, Days As Integer, Hours As Integer, Minutes As Integer, Seconds As Integer 
	Dim dm As Date, dw As Date, dd As Date, dh As Date, dn As Date, ds As Date 
	Dim ss As String, s0 As String = vbNullString, sb As New System.Text.StringBuilder 

	RetValues = RetValues.ToUpper 
	If RetValues.Length = 0 Then Return New SqlString() 

	If RetValues.IndexOf("Y") < 0 Then 
		dm = d1 
	Else 
		Years = CInt(DateDiff(DateInterval.Year, d1, d2)) 
		dm = DateAdd(DateInterval.Year, Years, d1) 
		If dm > d2 Then 
			Years -= 1 
			dm = DateAdd(DateInterval.Year, Years, d1) 
		End If 
		If Years > 0 Then 
			ss = Right(Years.ToString, 2) 
			If ss.EndsWith("0") Or ss.StartsWith("1") Or CInt(Right(ss, 1)) >= 5 Then 
				sb.Append(Years.ToString & " лет") 
			Else 
				sb.Append(Years.ToString & " год") 
				If Not ss.EndsWith("1") Then sb.Append("а") 
			End If 
		Else 
			s0 = "лет" 
		End If 
	End If 

	If RetValues.IndexOf("M") < 0 Then 
		dw = dm 
	Else 
		Months = CInt(DateDiff(DateInterval.Month, dm, d2)) 
		dw = DateAdd(DateInterval.Month, Months, dm) 
		If dw > d2 Then 
			Months -= 1 
			dw = DateAdd(DateInterval.Month, Months, dm) 
		End If 
		If Months > 0 Then 
			ss = Right((100 + Months).ToString, 2) 
			If sb.Length > 0 Then sb.Append(sr) 
			sb.Append(Months.ToString & " месяц") 
			If ss.EndsWith("0") Or ss.StartsWith("1") Or CInt(Right(ss, 1)) >= 5 Then 
				sb.Append("ев") 
			Else 
				If Not ss.EndsWith("1") Then sb.Append("а") 
			End If 
		Else 
			s0 = "месяцев" 
		End If 
	End If 

	If RetValues.IndexOf("W") < 0 Then 
		dd = dw 
	Else 
		Weeks = CInt(DateDiff(DateInterval.WeekOfYear, dw, d2)) 
		dd = DateAdd(DateInterval.WeekOfYear, Weeks, dw) 
		If dd > d2 Then 
			Weeks -= 1 
			dd = DateAdd(DateInterval.WeekOfYear, Weeks, dw) 
		End If 
		If Weeks > 0 Then 
			ss = Right((100 + Weeks).ToString, 2) 
			If sb.Length > 0 Then sb.Append(sr) 
			sb.Append(Weeks.ToString & " недел") 
			If ss.EndsWith("0") Or ss.StartsWith("1") Or CInt(Right(ss, 1)) >= 5 Then 
				sb.Append("ь") 
			Else 
				sb.Append(IIf(ss.EndsWith("1"), "я", "и")) 
			End If 
		Else 
			s0 = "недель" 
		End If 
	End If 

	If RetValues.IndexOf("D") < 0 Then 
		dh = dd 
	Else 
		Days = CInt(DateDiff(DateInterval.Day, dd, d2)) 
		dh = DateAdd(DateInterval.Day, Days, dd) 
		If dh > d2 Then 
			Days -= 1 
			dh = DateAdd(DateInterval.Day, Days, dd) 
		End If 
		If Days > 0 Then 
			ss = Right((100 + Days).ToString, 2) 
			If sb.Length > 0 Then sb.Append(sr) 
			sb.Append(Days.ToString & " д") 
			If ss.EndsWith("0") Or ss.StartsWith("1") Or CInt(Right(ss, 1)) >= 5 Then 
				sb.Append("ней") 
			Else 
				sb.Append(IIf(ss.EndsWith("1"), "ень", "ня")) 
			End If 
		Else 
			s0 = "дней" 
		End If 
	End If 

	If RetValues.IndexOf("H") < 0 Then 
		dn = dh 
	Else 
		Hours = CInt(DateDiff(DateInterval.Hour, dh, d2)) 
		dn = DateAdd(DateInterval.Hour, Hours, dh) 
		If dn > d2 Then 
			Hours -= 1 
			dn = DateAdd(DateInterval.Hour, Hours, dh) 
		End If 
		If Hours > 0 Then 
			ss = Right((100 + Hours).ToString, 2) 
			If sb.Length > 0 Then sb.Append(sr) 
			sb.Append(Hours.ToString & " час") 
			If ss.EndsWith("0") Or ss.StartsWith("1") Or CInt(Right(ss, 1)) >= 5 Then 
				sb.Append("ов") 
			Else 
				If Not ss.EndsWith("1") Then sb.Append("а") 
			End If 
		Else 
			s0 = "часов" 
		End If 
	End If 

	If RetValues.IndexOf("N") < 0 Then 
		ds = dn 
	Else 
		Minutes = CInt(DateDiff(DateInterval.Minute, dn, d2)) 
		ds = DateAdd(DateInterval.Minute, Minutes, dn) 
		If ds > d2 Then 
			Minutes -= 1 
			ds = DateAdd(DateInterval.Minute, Minutes, dn) 
		End If 
		If Minutes > 0 Then 
			ss = Right((100 + Minutes).ToString, 2) 
			If sb.Length > 0 Then sb.Append(sr) 
			sb.Append(Minutes.ToString & " минут") 
			If Not (ss.EndsWith("0") Or ss.StartsWith("1") Or CInt(Right(ss, 1)) >= 5) Then 
				sb.Append(IIf(ss.EndsWith("1"), "а", "ы")) 
			End If 
		Else 
			s0 = "минут" 
		End If 
	End If 

	If RetValues.IndexOf("N") >= 0 Then 
		Seconds = CInt(DateDiff(DateInterval.Second, ds, d2)) 
		If Seconds > 0 Then 
			ss = Right((100 + Seconds).ToString, 2) 
			If sb.Length > 0 Then sb.Append(sr) 
			sb.Append(Seconds.ToString & " секунд") 
			If Not (ss.EndsWith("0") Or ss.StartsWith("1") Or CInt(Right$(ss, 1)) >= 5) Then 
				sb.Append(IIf(ss.EndsWith("1"), "а", "ы")) 
			End If 
		Else 
			s0 = "секунд" 
		End If 
	End If 

	If sb.Length > 0 Then 
		Return New SqlString(sb.ToString) 
	Else 
		Return New SqlString("0 " & s0) 
	End If 
End Function 
End Class 

==========================================================================
Пример использования: 

[syntax="sql"]Select 
Лет = dbo.ufnGetAgo('19621010',GETDATE(), 'Y', 'Y'), 
Месяцев = dbo.ufnGetAgo('19621010',GETDATE(), 'M', 'YM'), 
ВсегоМесяцев = dbo.ufnGetAgo('19621010',GETDATE(), 'M', 'M'), 
[Возраст строкой] = dbo.ufnGetAgoString('19621010',GETDATE(), 'YMDHNS') 
UNION ALL 
Select 
Лет = dbo.ufnGetAgo('19621010',GETDATE(), 'Y', 'Y'), 
Месяцев = dbo.ufnGetAgo('19621010',GETDATE(), 'M', 'YM'), 
ВсегоМесяцев = dbo.ufnGetAgo('19921010',GETDATE(), 'M', 'M'), 
[Возраст строкой] = dbo.ufnGetAgoString('19921010',GETDATE(), 'YMDHNS') 
UNION ALL 
Select 
Лет = dbo.ufnGetAgo('19621010',GETDATE(), 'Y', 'Y'), 
Месяцев = dbo.ufnGetAgo('19621010',GETDATE(), 'M', 'YM'), 
ВсегоМесяцев = dbo.ufnGetAgo('19921010',GETDATE(), 'M', 'M'), 
[Возраст строкой] = dbo.ufnGetAgoString('19921015',GETDATE(), 'YMDHNS') 
UNION ALL 
Select 
Лет = dbo.ufnGetAgo('19621010',GETDATE(), 'Y', 'Y'), 
Месяцев = dbo.ufnGetAgo('19621010',GETDATE(), 'M', 'YM'), 
ВсегоМесяцев = dbo.ufnGetAgo('19921010',GETDATE(), 'M', 'M'), 
[Возраст строкой] = dbo.ufnGetAgoString('19921015',GETDATE(), 'wDHNS') 

-- И результат: 

Лет Месяцев ВсегоМесяцев Возраст строкой 
----------- ----------- ------------ -------------------------------------
43 5 521 43 года, 5 месяцев, 28 дней, 12 часов, 7 минут, 34 секунды 
43 5 161 13 лет, 5 месяцев, 28 дней, 12 часов, 7 минут, 34 секунды 
43 5 161 13 лет, 5 месяцев, 23 дня, 12 часов, 7 минут, 34 секунды 
43 5 161 703 недели, 1 день, 12 часов, 7 минут, 34 секунды 
6 сен 09, 01:18    [7622623]     Ответить | Цитировать Сообщить модератору
 Re: Функция расчета возраста  [new]
Joris
Member

Откуда:
Сообщений: 186
AndrF - На сколько я знаю это для 2005 -го или выше да, а для 2000 -го есть такая функция?
2 окт 09, 16:38    [7736267]     Ответить | Цитировать Сообщить модератору
 Re: Функция расчета возраста  [new]
AndrF
Member

Откуда:
Сообщений: 2194
Joris
AndrF - На сколько я знаю это для 2005 -го или выше да, а для 2000 -го есть такая функция?


Тут уже было просто влом делать - с 2000 я уже почти ушел (разве что парочку еще сопровождаю пока с них все не перенесли)...
6 окт 09, 11:27    [7746772]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить