誕生日が近い従業員を選択するストアドプロシージャを記述しようとしています。
SELECT * FROM Employees WHERE Birthday > @Today AND Birthday < @Today + @NumDays
これは、誕生日が誕生日の一部であるため機能しません。私の誕生日が'09 -18-1983 'の場合、'09 -18-2008'と'09 -25-2008 'の間には該当しません。
日付フィールドの年の部分を無視して月/日を比較する方法はありますか?
これは毎週月曜日の朝に実行され、今後の誕生日をマネージャーに警告するため、新しい年にまたがる可能性があります。
Kogusに感謝します。
SELECT * FROM Employees
WHERE Cast(DATEDIFF(dd, birthdt, getDate()) / 365.25 as int)
- Cast(DATEDIFF(dd, birthdt, futureDate) / 365.25 as int)
<> 0
注:これは、重大なバグと思われるものを修正するために編集しました。現在投稿されているバージョンでうまくいきます。
これは、データベースに対応するようにフィールド名とテーブル名を変更した後に機能します。
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))
基本的に、誕生日から現在までの日数を取得し、それを365で割ります(年に直接変換するときに発生する丸めの問題を回避するため)。
次に、誕生日から今から1週間までの日数を取得し、それを365で割って、今から1週間後の年齢を取得します。
彼らの誕生日が1週間以内の場合、これらの2つの値の差は1になります。したがって、これらのすべてのレコードが返されます。
誰かがMySQL(わずかに異なるコマンド)で解決策をまだ探している場合、クエリは次のとおりです。
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およびdateaddの最適な使用法。丸めなし、近似なし、2月29日のバグなし、日付関数のみ
ageOfThePerson = DATEDIFF(yyyy,dateOfBirth, GETDATE())
dateOfNextBirthday = DATEADD(yyyy,ageOfThePerson + 1, dateOfBirth)
daysBeforeBirthday = DATEDIFF(d,GETDATE(), dateofNextBirthday)
@Gustavo Cardosoのおかげで、人の年齢の新しい定義
ageOfThePerson = FLOOR(DATEDIFF(d,dateOfBirth, GETDATE())/365.25)
@strelcのアプローチが好きでしたが、彼のSQLは少しずれていました。これは、うまく機能し、使用が簡単な更新バージョンです。
SELECT * FROM User
WHERE (DATEDIFF(dd, getdate(), DATEADD(yyyy,
DATEDIFF(yyyy, birthdate, getdate()) + 1, birthdate)) + 1) % 366 <= <number of days>
2017年10月を編集:終了する1日を追加
私はこれに対する解決策を見つけました。これは誰かの貴重な時間を節約するかもしれません。
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 @nextDay=@nextDay + 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 @nextDay=@nextDay + 1
END
RETURN
END
日付で相互結合を作成し、月と日付の比較を確認します。
DAYOFYEAR
関数を使用することもできますが、12月の1月の誕生日を検索する場合は注意が必要です。お探しの日付範囲が新年に及ばない限り、大丈夫だと思います。
私の推測では、「365.25」の使用は遅かれ早かれ失敗するでしょう。
したがって、「365.25」を使用して実際のソリューションをテストすると、すべてのケースで同じ数の行が返されません。ここに例を示します:
http://sqlfiddle.com/#!3/94c3ce/7
2016年と2116年でテストすると、違いがわかります。私は1つのリンクしか投稿できませんが、両方のクエリを表示するには、de/7を/ 8に変更します。 (最初の答えは/ 10と/ 11)
したがって、この別のクエリをお勧めします。ポイントは、開始日から次の誕生日を決定し、それが私の興味の範囲内にあるかどうかを比較します。
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
申し訳ありませんが、年を無力化する必要があるとは思われませんでした。
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)
これはうまくいくはずです。
1か月以内に:
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() ))))
これはMS SQL Serverのソリューションです。誕生日が30日の従業員を返します。
SELECT * FROM rojstni_dnevi
WHERE (DATEDIFF (dd,
getdate(),
DATEADD ( yyyy,
DATEDIFF(yyyy, rDan, getdate()),
rDan)
nex )
+365) % 365 < 30
私はこれをMySQLに使用しましたが、おそらく最も効率的なクエリ方法ではありませんが、実装するのに十分簡単です。
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
を使用することもできます:
-- 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))
このソリューションは、翌年の誕生日と順序も考慮します:(dob =誕生日、bty =今年の誕生日、nbd =次の誕生日)
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
日付の比較を回避するこのバージョンは、より高速になる可能性があります。
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
範囲が翌年の2月29日をカバーする場合は、次を使用します。
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
より良くて簡単な解決策:
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、Nameを選択しますWHEN convert(nvarchar(5)、BirthDate、101)> convert(nvarchar(5)、GETDATE()、101)then 2 WHEN convert(nvarchar(5)、BirthDate、101)< convert(nvarchar(5)、GETDATE()、101)その後3 WHEN convert(nvarchar(5)、BirthDate、101)= convert(nvarchar(5)、GETDATE()、101)then 1 else 4 end、convert(nvarchar (2)、BirthDate、101)、convert(nvarchar(2)、BirthDate、105)
ナッツ!これについて考え始めたときと、答えに戻ったときの良い解決策です。 :)
私は思いついた:
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()を日時としてキャストする必要はありませんよね?
DATE_FORMAT を使用して、誕生日の日付の日と月の部分を抽出できます。
編集:申し訳ありませんが、彼がMySQLを使用していないことはわかりませんでした。
同じことを達成する最良の方法は
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)
数年前、大学のプロジェクトでも同じ問題に直面しました。私は年と日付(MM:DD)を2つの別々の列に分割して(かなりイタチの方法で)応答しました。その前に、私のプロジェクトメイトは単にすべての日付を取得し、プログラムでそれらを通過していました。あまりにも非効率的だったので、これを変更しました-私のソリューションがよりエレガントになったわけでもありません。また、複数のアプリによってしばらく使用されているデータベースでは、おそらくそれは不可能です。
これは、テストされたいくつかの回答の組み合わせです。これにより、特定の日付と年齢になる次の誕生日が見つかります。また、numdaysは、7日=週など、探している範囲を制限します。
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
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
;
年齢を取得するために325.25で除算したり、現在の年に誕生日をもたらすなどの解決策は、私にとってはうまくいきませんでした。これにより、2つのDaysOfTheYearの差分(1-366)が計算されます。今年まだ誕生日が迎えられていない場合は、残りの日数を自動的に取得し、比較することができます。誕生日が既に発生している場合は、remaining_daysは負の数になるため、現在の年の合計日数を加算することにより、残りの日数を正確に取得できます。うるう年も正しく処理されます。その場合、追加の日も追加されるためです(dayOfYear(Dec 31.)を使用)。
このチケットは何年も前にクローズされたと思いますが、正しいSQLクエリを取得するために、ぜひご覧ください。
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))
以下のクエリは、従業員の次の誕生日をすべて返します。これは最短のクエリです。
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 ;
上記のクエリは、現在の日付を除く翌月のすべてをカバーします。
これがT-SQLであると想定して、DATEPARTを使用して月と日付を別々に比較します。
http://msdn.Microsoft.com/en-us/library/ms174420.aspx
または、現在の年の1月1日を全員の誕生日から差し引いて、1900年(またはあなたのエポック年が何であれ)を使用して比較します。
これらのソリューションのほとんどは近いですが、いくつかの追加のシナリオを覚えておく必要があります。誕生日とスライディングスケールを使用する場合は、翌月への移行を処理できる必要があります。
たとえば、Stephensの例は、月の最後の4日までの誕生日に最適です。次に、今日が29日の場合の有効な日付が:29、30であり、次の月の1、2、3であるため、論理エラーが発生するので、これも条件付けする必要があります。
別の方法としては、誕生日フィールドから日付を解析し、現在の年のサブを解析してから、標準の範囲比較を行うことです。
もう1つの考え方:誕生日に年数を追加します(誕生日がまだ経過していない場合はもう1つ追加し、上記と同じように比較します。これを行うには、DATEPARTとDATEADDを使用します。
http://msdn.Microsoft.com/en-us/library/ms186819.aspx
1年にわたる範囲のEdgeケースには、特別なコードが必要です。
おまけのヒント:誕生日オペランドを繰り返す代わりに、BETWEEN ... ANDの使用を検討してください。
これを試してみてください:
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)
これはうまくいくはずです...
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))
これがあなたに何らかの形で役立つことを願っています...
select Employeename,DOB
from Employeemaster
where day(Dob)>day(getdate()) and month(DOB)>=month(getDate())
従業員の次の誕生日-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)