Yaklaşan doğum günleri olan çalışanları seçmek için saklı bir prosedür yazmaya çalışıyorum.
SELECT * FROM Employees WHERE Birthday > @Today AND Birthday < @Today + @NumDays
Bu işe yaramayacak çünkü doğum yılı Doğum Günü'nin bir parçası, eğer doğum günüm '09-18-1983' ise, '09 -18-2008' ile '09 -25-2008' arasında kalmayacak.
Tarih alanlarının yıl bölümünü yoksaymanın ve sadece ay/günleri karşılaştırmanın bir yolu var mı?
Bu her pazartesi sabahı gelecek doğum günlerinin yöneticilerini uyaracak, bu yüzden muhtemelen yeni yıllara yayılacak.
İşte yarattığım çalışma çözümü, teşekkürler Kogus.
SELECT * FROM Employees
WHERE Cast(DATEDIFF(dd, birthdt, getDate()) / 365.25 as int)
- Cast(DATEDIFF(dd, birthdt, futureDate) / 365.25 as int)
<> 0
Not: Önemli bir hata olduğuna inandığım şeyi düzeltmek için bunu düzenledim. Şu anda yayınlanan sürüm benim için çalışıyor.
Bu, alan ve tablo adlarını veritabanınıza karşılık gelecek şekilde değiştirdikten sonra çalışmalıdır.
SELECT
BRTHDATE AS BIRTHDAY
,FLOOR(DATEDIFF(dd,EMP.BRTHDATE,GETDATE()) / 365.25) AS AGE_NOW
,FLOOR(DATEDIFF(dd,EMP.BRTHDATE,GETDATE()+7) / 365.25) AS AGE_ONE_WEEK_FROM_NOW
FROM
"Database name".dbo.EMPLOYEES EMP
WHERE 1 = (FLOOR(DATEDIFF(dd,EMP.BRTHDATE,GETDATE()+7) / 365.25))
-
(FLOOR(DATEDIFF(dd,EMP.BRTHDATE,GETDATE()) / 365.25))
Temel olarak, doğum günlerinden bugüne günlerin sayısını alır ve bunu 365'e böler (doğrudan yıllara dönüştürdüğünüzde ortaya çıkan yuvarlama sorunlarını önlemek için).
Daha sonra doğum günlerinden bir hafta öncesine kadar olan günlerin sayısını alır ve bundan bir hafta sonra yaşlarını almak için bunu 365'e böler.
Doğum günleri bir hafta içinde ise, bu iki değer arasındaki fark 1 olacaktır. Böylece tüm bu kayıtları döndürür.
Birisinin hala MySQL (biraz farklı komutlar) içinde bir çözüm aradığı durumda, burada sorgusu:
SELECT
name,birthday,
FLOOR(DATEDIFF(DATE(NOW()),birthday) / 365.25) AS age_now,
FLOOR(DATEDIFF(DATE_ADD(DATE(NOW()),INTERVAL 30 DAY),birthday) / 365.25) AS age_future
FROM user
WHERE 1 = (FLOOR(DATEDIFF(DATE_ADD(DATE(NOW()),INTERVAL 30 DAY),birthday) / 365.25)) - (FLOOR(DATEDIFF(DATE(NOW()),birthday) / 365.25))
ORDER BY MONTH(birthday),DAY(birthday)
Datediff ve dateadd'ın en iyi kullanımı. Yuvarlama yok, yaklaşık yok, 29 şubat böceği yok, tarih fonksiyonlarından başka bir şey yok
ageOfThePerson = DATEDIFF(yyyy,dateOfBirth, GETDATE())
dateOfNextBirthday = DATEADD(yyyy,ageOfThePerson + 1, dateOfBirth)
daysBeforeBirthday = DATEDIFF(d,GETDATE(), dateofNextBirthday)
@Gustavo Cardoso'ya teşekkürler, kişinin yaşı için yeni tanım
ageOfThePerson = FLOOR(DATEDIFF(d,dateOfBirth, GETDATE())/365.25)
@Strelc'in yaklaşımını sevdim, fakat onun sql'si biraz kapalıydı. İşte iyi çalışan ve kullanımı basit bir güncellenmiş sürümü:
SELECT * FROM User
WHERE (DATEDIFF(dd, getdate(), DATEADD(yyyy,
DATEDIFF(yyyy, birthdate, getdate()) + 1, birthdate)) + 1) % 366 <= <number of days>
10/2017 düzenle: bitiş için tek bir gün ekle
Bunun için çözümü buldum. Bu birinin değerli zamanını kurtarabilir.
select EmployeeID,DOB,dates.date from emp_tb_eob_employeepersonal
cross join dbo.GetDays(Getdate(),Getdate()+7) as dates where weekofmonthnumber>0
and month(dates.date)=month(DOB) and day(dates.date)=day(DOB)
GO
/****** Object: UserDefinedFunction [dbo].[GetDays] Script Date: 11/30/2011 13:19:17 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
--SELECT [dbo].[GetDays] ('02/01/2011','02/28/2011')
ALTER FUNCTION [dbo].[GetDays](@startDate datetime, @endDate datetime)
RETURNS @retValue TABLE
(Days int ,Date datetime, WeekOfMonthNumber int, WeekOfMonthDescription varchar(10), DayName varchar(10))
AS
BEGIN
DECLARE @nextDay int
DECLARE @nextDate datetime
DECLARE @WeekOfMonthNum int
DECLARE @WeekOfMonthDes varchar(10)
DECLARE @DayName varchar(10)
SELECT @nextDate = @startDate, @WeekOfMonthNum = DATEDIFF(week, DATEADD(MONTH, DATEDIFF(MONTH,0,@startDate),0),@startDate) + 1,
@WeekOfMonthDes = CASE @WeekOfMonthNum
WHEN '1' THEN 'First'
WHEN '2' THEN 'Second'
WHEN '3' THEN 'Third'
WHEN '4' THEN 'Fourth'
WHEN '5' THEN 'Fifth'
WHEN '6' THEN 'Sixth'
END,
@DayName
= DATENAME(weekday, @startDate)
SET @nextDay=1
WHILE @nextDate <= @endDate
BEGIN
INSERT INTO @retValue values (@nextDay,@nextDate, @WeekOfMonthNum, @WeekOfMonthDes, @DayName)
SELECT @[email protected] + 1
SELECT @nextDate = DATEADD(day,1,@nextDate),
@WeekOfMonthNum
= DATEDIFF(week, DATEADD(MONTH, DATEDIFF(MONTH,0, @nextDate),0), @nextDate) + 1,
@WeekOfMonthDes
= CASE @WeekOfMonthNum
WHEN '1' THEN 'First'
WHEN '2' THEN 'Second'
WHEN '3' THEN 'Third'
WHEN '4' THEN 'Fourth'
WHEN '5' THEN 'Fifth'
WHEN '6' THEN 'Sixth'
END,
@DayName
= DATENAME(weekday, @nextDate)
CONTINUE
END
WHILE(@nextDay <=31)
BEGIN
INSERT INTO @retValue values (@nextDay,@nextDate, 0, '', '')
SELECT @[email protected] + 1
END
RETURN
END
Tarihlerle bir haç yapın ve ay ile tarihlerin karşılaştırmasını kontrol edin.
DAYOFYEAR
işlevini kullanabilirsiniz, ancak Aralık ayında Ocak doğum günlerini aramak istediğinizde dikkatli olun. Sanırım aradığınız tarih aralığı Yeni Yılı yaymadığı sürece iyi olacaksınız.
Tahminim, "365.25" i çok yakında kullanıyorsa başarısız olur.
Bu nedenle çalışma çözümünü "365.25" kullanarak test ediyorum ve Her durum için aynı sayıda satırı döndürmüyorum. İşte bir örnek:
http://sqlfiddle.com/#!3/94c3ce/7
yıl 2016 ve 2116 ile test ve farkı göreceksiniz. Yalnızca bir bağlantı gönderebilirim/her ikisini de sorgulamak için de/7// 8 ile değiştirebilirim. (İlk cevap için/10 ve/11)
Bu yüzden, bir sonraki sorgunun başlangıç tarihinden itibaren bir sonraki doğum gününü belirlediği bir sorguyu daha sonra öneririm ve ilgilendiğim aralıkta ise karşılaştırın.
SELECT * FROM Employees
WHERE
CASE WHEN (DATEADD(yyyy,DATEDIFF(yyyy, birthdt, @fromDate),birthdt) < @fromDate )
THEN DATEADD(yyyy,DATEDIFF(yyyy, birthdt, @fromDate)+1,birthdt)
ELSE DATEADD(yyyy,DATEDIFF(yyyy, birthdt, @fromDate),birthdt) END
BETWEEN @fromDate AND @toDate
Maalesef yılı etkisiz hale getirme gereğini görmedim.
select * from Employees
where DATEADD (year, DatePart(year, getdate()) - DatePart(year, Birthday), Birthday)
between convert(datetime, getdate(), 101)
and convert(datetime, DateAdd(day, 5, getdate()), 101)
Bu çalışmalı.
Bir aydan az bir sürede:
SELECT * FROM people WHERE MOD( DATEDIFF( CURDATE( ) , `date_birth`) /30, 12 ) <1 and (((month(`date_birth`)) = (month(curdate())) and (day(`date_birth`)) > (day (curdate() ))) or ((month(`date_birth`)) > (month(curdate())) and (day(`date_birth`)) < (day (curdate() ))))
Bu, MS SQL Server için bir çözümdür: Doğum günleri olan çalışanları 30 gün içinde iade eder.
SELECT * FROM rojstni_dnevi
WHERE (DATEDIFF (dd,
getdate(),
DATEADD ( yyyy,
DATEDIFF(yyyy, rDan, getdate()),
rDan)
nex )
+365) % 365 < 30
Bunu MySQL için kullandım, muhtemelen sorgulamanın en etkili yolu değil, uygulaması basit.
select * from `schema`.`table` where date_format(birthday,'%m%d') >= date_format(now(),'%m%d') and date_format(birthday,'%m%d') < date_format(DATE_ADD(NOW(), INTERVAL 5 DAY),'%m%d');
DATEPART
öğesini de kullanabilirsiniz:
-- To find out Today's Birthday
DECLARE @today DATETIME
SELECT @today = getdate()
SELECT *
FROM SMIS_Registration
WHERE (DATEPART (month, DOB) >= DATEPART (month, @today)
AND DATEPART (day, DOB) = DATEPART (day, @today))
Bu çözüm, gelecek yıl doğum günleri ve siparişleri de dikkate alır: (dob = doğum günü; bty = bu yıl doğum günü; nbd = sonraki doğum günü)
with rs (bty) as (
SELECT DATEADD(Year, DATEPART(Year, GETDATE()) - DATEPART(Year, dob), dob) as bty FROM Employees
),
rs2 (nbd) as (
select case when bty < getdate() then DATEADD(yyyy, 1, bty) else bty end as nbd from rs
)
select nbd, DATEDIFF(d, getdate(), nbd) as diff from rs2 where DATEDIFF(d, getdate(), nbd) < 14 order by diff
Tarihlerin karşılaştırılmasını engelleyen bu sürüm daha hızlı olabilir:
with rs (dob, bty) as (
SELECT dob, DATEADD(Year, DATEPART(Year, GETDATE()) - DATEPART(Year, DOB), DOB) as bty FROM employee
),
rs2 (dob, nbd) as (
select dob, DATEADD(yyyy, FLOOR(ABS((-1*(SIGN(DATEDIFF(d, getdate(), bty))))+0.1)), bty) as nbd from rs
),
rs3 (dob, diff) as (
select dob, datediff(d, getdate(), nbd) as diff from rs2
)
select dob, diff from rs3 where diff < 14 order by diff
Aralık, gelecek yıl 29 Şubat’ı kapsıyorsa, şunları kullanın:
with rs (dob, ydiff) as (
select dob, DATEPART(Year, GETDATE()) - DATEPART(Year, DOB) as ydiff from Employee
),
rs2 (dob, bty, ydiff) as (
select dob, DATEADD(Year, ydiff, dob) as bty, ydiff from rs
),
rs3 (dob, nbd) as (
select dob, DATEADD(yyyy, FLOOR(ABS((-1*(SIGN(DATEDIFF(d, getdate(), bty))))+0.1)) + ydiff, dob) as nbd from rs2
),
rs4 (dob, ddiff, nbd) as (
select dob, datediff(d, getdate(), nbd) as diff, nbd from rs3
)
select dob, nbd, ddiff from rs4 where ddiff < 68 order by ddiff
Daha iyi ve kolay çözüm:
select * from users with(nolock)
where date_of_birth is not null
and
(
DATEDIFF(dd,
DATEADD(yy, -(YEAR(GETDATE())-1900),GETDATE()), --Today
DATEADD(yy, -(YEAR(date_of_birth)-1901),date_of_birth)
) % 365
) = 30
birthDate'i seçin, Çalışanlar adına göre sırayla Case WHEN dönüşümü (nvarchar (5), BirthDate, 101)> convert (nvarchar (5), GETDATE (), 101) sonra 2 WHEN dönüşümü (nvarchar (5), BirthDate, 101) < dönüştürmek (nvarchar (5), GETDATE (), 101) sonra 3 WHEN dönüştürmek (nvarchar (5), BirthDate, 101) = dönüştürmek (nvarchar (5), GETDATE (), 101) sonra 1 başka 4 son, dönüştürmek (nvarchar (2), doğum tarihi, 101) dönüştürmek (nvarchar (2), doğum tarihi, 105)
Cari ay doğum günü
SELECT * FROM tblMember m
WHERE m.GDExpireDate != ''
AND CONVERT(CHAR(2),CONVERT(datetime, m.dob, 103), 101) = CONVERT(CHAR(2), GETDATE(), 101)
AND CONVERT(CHAR(2),CONVERT(datetime, m.dob, 103), 103) >= CONVERT(CHAR(2), GETDATE(), 103)
Fındık! Bunu düşünmeye başladığımda ve cevaplamaya geri döndüğümde iyi bir çözüm. :)
Ben geldim:
select (365 + datediff(d,getdate(),cast(cast(datepart(yy,getdate()) as varchar(4)) + '-' + cast(datepart(m,birthdt) as varchar(2)) + '-' + cast(datepart(d,birthdt) as varchar(2)) as datetime))) % 365
from employees
where (365 + datediff(d,getdate(),cast(cast(datepart(yy,getdate()) as varchar(4)) + '-' + cast(datepart(m,birthdt) as varchar(2)) + '-' + cast(datepart(d,birthdt) as varchar(2)) as datetime))) % 365 < @NumDays
Getdate () 'yi bir tarih olarak kullanmanız gerekmez, değil mi?
Doğum tarihlerinin gün ve ay bölümlerini çıkarmak için DATE_FORMAT kullanabilirsiniz.
EDIT: üzgünüm MySQL kullanmadığını görmedim.
Aynı elde etmenin en iyi yolu
DECLARE @StartDate DATETIME
DECLARE @EndDate DATETIME
SELECT Member.* from vwMember AS Member
WHERE (DATEADD(YEAR, (DATEPART(YEAR, @StartDate) -
DATEPART(YEAR, Member.dBirthDay)), Member.dBirthDay)
BETWEEN @StartDate AND @EndDate)
Aynı problemi birkaç yıl önce üniversite projemle de karşıladım. Yıl ve tarihi (MM: DD) iki ayrı sütuna bölerek (oldukça zayıf bir şekilde) cevap verdim. Ve bundan önce, proje arkadaşım sadece bütün tarihleri almaktı ve programatik olarak onlardan geçiyordu. Bunu değiştirdik, çünkü bu çok verimsizdi - benim çözümümün daha da zarif olması değildi. Ayrıca, bir süredir çoklu uygulamalar tarafından kullanılmakta olan bir veritabanında yapılması da mümkün değildir.
Bu, test edilen cevapların birkaçının birleşimidir. Bu, bir sonraki brithday’i belirli bir tarihten ve yaşa girecekleri günden sonra bulacak. Ayrıca numdays, aradığınız aralığı 7 gün = hafta vb. Sınırlar.
SELECT DISTINCT FLOOR(DATEDIFF(dd,Birthday, @BeginDate) / 365.25) + 1 age,
DATEADD(yyyy, FLOOR(DATEDIFF(dd,Birthday, @BeginDate) / 365.25) + 1, Birthday) nextbirthday, birthday
FROM table
WHERE DATEADD(yyyy, FLOOR(DATEDIFF(dd,Birthday, @BeginDate) / 365.25) + 1, Birthday) > @BeginDate
AND DATEADD(yyyy, FLOOR(DATEDIFF(dd,Birthday, @BeginDate) / 365.25) + 1, Birthday) < DATEADD(dd, @NumDays, @BeginDate)
order by nextbirthday
Çözüm SQLite:
SELECT
*,
strftime('%j', birthday) - strftime('%j', 'now') AS days_remaining
FROM
person
WHERE :n_days >= CASE
WHEN days_remaining >= 0 THEN days_remaining
ELSE days_remaining + strftime('%j', strftime('%Y-12-31', 'now'))
END
;
Yaşı almak için doğum tarihini 325.25'e bölen veya doğum tarihini şimdiki yıla vb. Getiren çözümler benim için işe yaramadı. Bu, iki günün deltalarını hesaplar. TheYear'ın (1-366). Doğum günü henüz bu yıl gerçekleşmediyse, karşılaştırabileceğiniz doğru gün sayısını otomatik olarak alırsınız. Doğum günü zaten olmuşsa, kalan günler negatiftir ve geçerli yıldaki toplam gün sayısını ekleyerek kalan gün sayısını doğru alabilirsiniz. Bu aynı zamanda artık yılları da doğru şekilde işler, çünkü bu durumda fazladan bir gün de eklenir (dayOfYear kullanarak (Aralık 31.))
bu biletin yıllar önce kapatıldığına inanıyorum, ancak doğru sql sorgusunu elde etmek için lütfen bir göz atın.
SELECT Employee_Name, DATE_OF_BIRTH
FROM Hr_table
WHERE
/**
fetching the original birth_date and replacing the birth year to the current but have to deduct 7 days to adjust jan 1-7 birthdate.
**/
datediff(d,getdate(),DATEADD(year,datediff(year,DATEADD(d,-7,hr.DATE_OF_BIRTH),getdate()),hr.date_of_birth)) between 0 and 7
-- current date looks ahead to 7 days for upcoming modified year birth date.
order by
-- sort by no of days before the birthday
datediff(d,getdate(),DATEADD(year,datediff(year,DATEADD(d,-7,hr.DATE_OF_BIRTH),getdate()),hr.date_of_birth))
Sorgunun altında çalışanın tüm doğum gününü döndürecek, en kısa sorgudur.
SELECT
Employee.DOB,
DATEADD(
mm,
(
(
(
(
DATEPART(yyyy, getdate())-DATEPART(yyyy, Employee.DOB )
)
+
(
1-
(
((DATEPART(mm, Employee.DOB)*100)+DATEPART(dd, Employee.DOB))
/
((DATEPART(mm, getdate())*100) + DATEPART(dd, getdate()))
)
)
)
*12
)
),
Employee.DOB
) NextDOB
FROM
Employee
ORDER BY
NextDOB ;
Yukarıdaki sorgu, geçerli tarih hariç tüm gelecek ayları kapsayacak.
Bunun T-SQL olduğunu varsayarak, ayı ve tarihi ayrı olarak karşılaştırmak için DATEPART kullanın.
http://msdn.Microsoft.com/en-us/library/ms174420.aspx
Alternatif olarak, bu yılın 1 Ocak tarihini herkesin doğum gününden çıkarın ve 1900 yılını (veya Epoch yılınız ne olursa olsun) kullanarak karşılaştırın.
Bu çözümlerin çoğu yakın, ancak birkaç ilave senaryoyu hatırlamanız gerekiyor. Doğum günleri ve kayan bir ölçekle çalışırken, bir sonraki aya geçişi gerçekleştirebilmelisiniz.
Örneğin Stephens örneği, doğum günleri için ayın son 4 gününe kadar harika çalışır. Öyleyse, eğer 29'unda bugün olsaydı geçerli tarihler olarak bir mantık arızası yaşarsınız: 29, 30, VE SONRAKİ ayın 1, 2, 3'ü.
Bir alternatif doğum günü alanından tarih ayrıştırmak ve cari yıl alt, sonra standart bir aralık karşılaştırması yapmak olacaktır.
Başka bir düşünce: Yaşlarını bütün yıllar içinde doğum günlerine ekleyin (veya Doğum günleri henüz gerçekleşmediyse bir tane daha yapın ve sonra yukarıda yaptığınız gibi karşılaştırın. Bunu yapmak için DATEPART ve DATEADD kullanın.
http://msdn.Microsoft.com/en-us/library/ms186819.aspx
Yılı kapsayan bir aralıktaki Edge durumunun özel bir kodu olması gerekir.
Bonus ipucu: Birthday operandını tekrarlamak yerine BETWEEN ... AND kullanmayı düşünün.
Bunu bir deneyin:
SELECT * FROM Employees
WHERE DATEADD(yyyy, DATEPART(yyyy, @Today)-DATEPART(yyyy, Birthday), Birthday) > @Today
AND DATEADD(yyyy, DATEPART(yyyy, @Today)-DATEPART(yyyy, Birthday), Birthday) < DATEADD(dd, @NumDays, @Today)
Bu çalışmalı...
DECLARE @endDate DATETIME
DECLARE @today DATETIME
SELECT @endDate = getDate()+6, @today = getDate()
SELECT * FROM Employees
WHERE
(DATEPART (month, birthday) >= DATEPART (month, @today)
AND DATEPART (day, birthday) >= DATEPART (day, @today))
AND
(DATEPART (month, birthday) < DATEPART (month, @endDate)
AND DATEPART (day, birthday) < DATEPART (day, @endDate))
Umarım bu size bir şekilde yardımcı olur ....
select Employeename,DOB
from Employeemaster
where day(Dob)>day(getdate()) and month(DOB)>=month(getDate())
Çalışan için Yaklaşan Doğum Günü - Sqlserver
DECLARE @sam TABLE
(
EmployeeIDs int,
dob datetime
)
INSERT INTO @sam (dob, EmployeeIDs)
SELECT DOBirth, EmployeeID FROM Employee
SELECT *
FROM
(
SELECT *, bd_this_year = DATEADD(YEAR, DATEPART(YEAR, GETDATE()) - DATEPART(YEAR, dob), dob)
FROM @sam s
) d
WHERE d.bd_this_year > DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()), 0)
AND d.bd_this_year <= DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()), 3)