J'essaie d'écrire une procédure stockée pour sélectionner les employés qui ont des anniversaires à venir.
SELECT * FROM Employees WHERE Birthday > @Today AND Birthday < @Today + @NumDays
Cela ne fonctionnera pas car l'année de naissance fait partie de l'anniversaire. Par conséquent, si mon anniversaire était '09 -18-1983 ', il ne tombera pas entre '09 -18-2008' et '09 -25-2008 '.
Existe-t-il un moyen d'ignorer la partie année des champs de date et de simplement comparer mois/jours?
Cette opération aura lieu tous les lundis matins pour alerter les responsables des anniversaires à venir, de sorte qu’elle couvrira probablement les années à venir.
Voici la solution de travail que j'ai finalement créée, merci Kogus.
SELECT * FROM Employees
WHERE Cast(DATEDIFF(dd, birthdt, getDate()) / 365.25 as int)
- Cast(DATEDIFF(dd, birthdt, futureDate) / 365.25 as int)
<> 0
Note: J'ai édité cela pour corriger ce qui, à mon avis, était un bug important. La version actuellement affichée fonctionne pour moi.
Cela devrait fonctionner une fois que vous avez modifié les noms de champs et de tables afin qu'ils correspondent à votre base de données.
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))
En gros, il obtient le nombre de jours de son anniversaire à maintenant et le divise par 365 (pour éviter les problèmes d'arrondi lorsque vous convertissez directement en années).
Ensuite, il passe le nombre de jours de leur anniversaire à une semaine à partir de maintenant et le divise par 365 pour obtenir leur âge une semaine à partir de maintenant.
Si leur date de naissance est dans une semaine, la différence entre ces deux valeurs sera égale à 1. Elle renvoie donc tous ces enregistrements.
Si quelqu'un cherche toujours une solution dans MySQL (commandes légèrement différentes), voici la requête:
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)
Meilleure utilisation de datiff et dateadd. Pas d'arrondi, pas d'approximation, pas de bug du 29 février, rien que des fonctions de date
ageOfThePerson = DATEDIFF(yyyy,dateOfBirth, GETDATE())
dateOfNextBirthday = DATEADD(yyyy,ageOfThePerson + 1, dateOfBirth)
daysBeforeBirthday = DATEDIFF(d,GETDATE(), dateofNextBirthday)
Grâce à @Gustavo Cardoso, nouvelle définition de l'âge de la personne
ageOfThePerson = FLOOR(DATEDIFF(d,dateOfBirth, GETDATE())/365.25)
A aimé l'approche de @strelc, mais son sql était un peu en retrait. Voici une version mise à jour qui fonctionne bien et est simple à utiliser:
SELECT * FROM User
WHERE (DATEDIFF(dd, getdate(), DATEADD(yyyy,
DATEDIFF(yyyy, birthdate, getdate()) + 1, birthdate)) + 1) % 366 <= <number of days>
edit 10/2017: ajouter un jour à la fin
J'ai trouvé la solution pour cela. Cela peut sauver le temps précieux de quelqu'un.
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
Faites un croisement avec les dates et vérifiez la comparaison du mois et des dates.
Vous pouvez utiliser la fonction DAYOFYEAR
mais soyez prudent lorsque vous souhaitez rechercher les anniversaires de janvier en décembre. Je pense que tout ira bien tant que la plage de dates que vous recherchez ne couvre pas le Nouvel An.
À mon avis, utiliser "365.25" tôt ou tard serait un échec.
J'ai donc testé la solution de travail en utilisant "365.25" Et elle ne renvoie pas le même nombre de lignes pour chaque cas. Voici un exemple:
http://sqlfiddle.com/#!3/94c3ce/7
testez avec les années 2016 et 2116 et vous verrez la différence. Je ne peux publier qu'un seul lien mais changer de/7 par/8 pour voir les deux requêtes. (/ 10 et/11 pour la première réponse)
Donc, je suggère cette autre requête, où le point est déterminé le prochain anniversaire de naissance à partir d’une date de début, puis compare si c’est dans mon domaine d’intérêt.
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
Désolé n'a pas vu l'obligation de neutraliser l'année.
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)
Cela devrait marcher.
En moins d'un mois:
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() ))))
Ceci est une solution pour MS SQL Server: Elle renvoie les employés avec un anniversaire dans les 30 jours.
SELECT * FROM rojstni_dnevi
WHERE (DATEDIFF (dd,
getdate(),
DATEADD ( yyyy,
DATEDIFF(yyyy, rDan, getdate()),
rDan)
nex )
+365) % 365 < 30
J'ai utilisé cela pour MySQL , probablement pas le moyen le plus efficace d'interroger mais assez simple à implémenter.
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');
Vous pouvez également utiliser 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))
Cette solution prend également en charge les anniversaires de l'année suivante et la commande: (Dob = jour de naissance; bty = anniversaire cette année; nbd = anniversaire suivant)
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
Cette version, qui évite la comparaison des dates, pourrait être plus rapide:
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
Si la plage couvre le 29 février de l'année suivante, utilisez:
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
Solution simple et meilleure:
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
sélectionnez Date de naissance, Nom des employés par cas QUAND convertir (nvarchar (5), Date de naissance, 101)> convertir (nvarchar (5), GETDATE (), 101), puis 2 WHEN convertir (nvarchar (5), BirthDate, 101) <convert (nvarchar (5), GETDATE (), 101) puis 3 WHEN convertir (nvarchar (5), BirthDate, 101) = convertir ( nvarchar (5), GETDATE (), 101) puis 1 autre 4 terminent, convertissent (nvarchar (2), date de naissance, 101), convertissent (nvarchar (2), date de naissance, 105)
Anniversaire du mois en cours
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)
Des noisettes! Une bonne solution entre le moment où j'ai commencé à y penser et le moment où je suis revenu pour y répondre. :)
Je suis venu avec:
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
Vous n'avez pas besoin de convertir getdate () en tant que date/heure, n'est-ce pas?
Vous pouvez utiliser DATE_FORMAT pour extraire les parties jour et mois des dates de naissance.
EDIT: désolé, je n'ai pas vu qu'il n'utilisait pas MySQL.
Le meilleur moyen de réaliser la même chose est
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)
J'ai eu le même problème avec mon projet de collège il y a quelques années. J'ai répondu (d'une manière plutôt étrange) en scindant l'année et la date (MM: DD) en deux colonnes distinctes. Et avant cela, mon compagnon de projet obtenait simplement toutes les dates et les parcourait de manière programmée. Nous avons changé cela parce que c'était trop inefficace - non pas que ma solution soit plus élégante non plus. En outre, il est probablement impossible de le faire dans une base de données utilisée depuis un certain temps par plusieurs applications.
Ceci est une combinaison de quelques réponses qui ont été testées. Cela trouvera le lendemain brithday après une certaine date et l'âge qu'ils seront. De plus, le nombre de jours limitera la plage que vous recherchez 7 jours = semaine, etc.
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
je crois que ce billet a été fermé il y a bien longtemps, mais pour en savoir plus sur la requête SQL correcte, jetez un coup d'œil.
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))
La requête ci-dessous renverra tous les prochains anniversaires d'employé, c'est la requête la plus courte.
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 ;
La requête ci-dessus couvrira tout le mois prochain, à l’exclusion de la date du jour.
En supposant qu'il s'agisse de T-SQL, utilisez DATEPART pour comparer le mois et la date séparément.
http://msdn.Microsoft.com/en-us/library/ms174420.aspx
Vous pouvez également soustraire le 1er janvier de l'année en cours à l'anniversaire de chacun, puis effectuer une comparaison en utilisant l'année 1900 (ou quelle que soit votre année d'époque).
La plupart de ces solutions sont proches, mais vous devez vous rappeler quelques scénarios supplémentaires. Lorsque vous travaillez avec des anniversaires et une échelle mobile, vous devez être capable de gérer la transition vers le mois prochain.
Par exemple, l'exemple de Stephens convient parfaitement aux anniversaires jusqu'aux 4 derniers jours du mois. Ensuite, vous avez un défaut de logique car les dates valides si le 29 était aujourd’hui seraient: 29, 30, et ensuite 1, 2, 3 du mois suivant, vous devez donc vous aussi vous préparer.
Une alternative serait d’analyser la date à partir du champ Anniversaire et de l’année en cours, puis de faire une comparaison de plage standard.
Une autre pensée: Ajoutez leur âge en années entières à leur anniversaire (ou un autre si leur anniversaire n’a pas encore eu lieu, puis comparez comme vous le faites ci-dessus. Utilisez DATEPART et DATEADD pour le faire.
http://msdn.Microsoft.com/en-us/library/ms186819.aspx
Le cas Edge d'une plage couvrant l'année devrait avoir un code spécial.
Conseil bonus: pensez à utiliser BETWEEN ... AND au lieu de répéter l’opérande Anniversaire.
Essayez ceci:
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)
Cela devrait marcher ...
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))
J'espère que cela vous aide d'une certaine façon ...
select Employeename,DOB
from Employeemaster
where day(Dob)>day(getdate()) and month(DOB)>=month(getDate())
Anniversaire à venir pour l'employé - 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)