ejemplos - SQL Select próximos cumpleaños
select sql server (30)
Intento escribir un procedimiento almacenado para seleccionar empleados que tengan cumpleaños próximos.
SELECT * FROM Employees WHERE Birthday > @Today AND Birthday < @Today + @NumDays
Esto no funcionará porque el año de nacimiento es parte del cumpleaños, por lo que si mi cumpleaños fue ''09 -18-1983 '', eso no estará entre ''09 -18-2008'' y ''09 -25-2008 ''.
¿Hay alguna forma de ignorar la porción del año de los campos de fecha y simplemente comparar mes / día?
Esto se ejecutará todos los lunes por la mañana para alertar a los gerentes de cumpleaños próximos, por lo que posiblemente abarcará los años nuevos.
Aquí está la solución de trabajo que terminé creando, gracias Kogus.
SELECT * FROM Employees
WHERE Cast(DATEDIFF(dd, birthdt, getDate()) / 365.25 as int)
- Cast(DATEDIFF(dd, birthdt, futureDate) / 365.25 as int)
<> 0
¡Nueces! Una buena solución entre cuando comencé a pensar en esto y cuando volví para responder. :)
Se me ocurrio:
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
No es necesario convertir getdate () como fecha y hora, ¿verdad?
Creo que este ticket se ha cerrado hace años, pero para obtener la consulta sql correcta, eche un vistazo.
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))
El mejor uso de datediff y dateadd. Sin redondeo, sin aproximaciones, sin error del 29 de febrero, nada más que las funciones de fecha
ageOfThePerson = DATEDIFF(yyyy,dateOfBirth, GETDATE())
dateOfNextBirthday = DATEADD(yyyy,ageOfThePerson + 1, dateOfBirth)
daysBeforeBirthday = DATEDIFF(d,GETDATE(), dateofNextBirthday)
Gracias a @Gustavo Cardoso, nueva definición para la edad de la persona
-
ageOfThePerson = FLOOR(DATEDIFF(d,dateOfBirth, GETDATE())/365.25)
En caso de que alguien todavía esté buscando una solución en MySQL (comandos ligeramente diferentes), aquí está la consulta:
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)
En menos de un mes:
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() ))))
Encontré la solución para esto. Esto puede salvar el valioso tiempo de alguien.
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
Haga una combinación cruzada con las fechas y verifique la comparación de mes y fechas.
Enfrenté el mismo problema con mi proyecto universitario hace unos años. Respondí (de una manera bastante comadreja) dividiendo el año y la fecha (MM: DD) en dos columnas separadas. Y antes de eso, mi compañero de proyecto simplemente estaba obteniendo todas las fechas y pasando programáticamente por ellas. Cambiamos eso porque era demasiado ineficiente; no es que mi solución fuera tampoco más elegante. Además, probablemente no sea posible hacerlo en una base de datos que ha estado en uso por un tiempo por varias aplicaciones.
Espero que esto te ayude de alguna manera ...
select Employeename,DOB
from Employeemaster
where day(Dob)>day(getdate()) and month(DOB)>=month(getDate())
Esta es una combinación de algunas de las respuestas que se probaron. Esto encontrará el próximo día después de una fecha determinada y la edad que tendrán. Además, los días límites limitarán el rango que está buscando los 7 días = semana, 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
Esta es una solución para MS SQL Server: Devuelve empleados con cumpleaños en 30 días.
SELECT * FROM rojstni_dnevi
WHERE (DATEDIFF (dd,
getdate(),
DATEADD ( yyyy,
DATEDIFF(yyyy, rDan, getdate()),
rDan)
nex )
+365) % 365 < 30
Esta solución también se ocupa de los cumpleaños en el próximo año y del orden: (dob = día de nacimiento; bty = cumpleaños este año; nbd = próximo cumpleaños)
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
Esta versión, que evita la comparación de las fechas, podría ser más rápida:
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 el rango cubre el 29 de febrero del año siguiente, utilice:
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
Esto debería funcionar...
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))
La mayoría de estas soluciones están cerca, pero debes recordar algunos escenarios adicionales. Al trabajar con cumpleaños y una escala móvil, debe ser capaz de manejar la transición al mes siguiente.
Por ejemplo, el ejemplo de Stephens funciona muy bien para cumpleaños hasta los últimos 4 días del mes. Entonces tiene una falla lógica, ya que las fechas válidas si hoy fuera el día 29 serían: 29, 30, Y luego 1, 2, 3 del PRÓXIMO mes, por lo que debe condicionarlo también.
Una alternativa sería analizar la fecha del campo de cumpleaños, y el subtítulo en el año actual, luego hacer una comparación de rango estándar.
La mejor manera de lograr lo mismo es
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)
Lo siento, no vi el requisito de neutralizar el año.
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)
Esto debería funcionar.
Me gustó el enfoque de @strelc, pero su sql estaba un poco apagado. Aquí hay una versión actualizada que funciona bien y es simple de usar:
SELECT * FROM User
WHERE (DATEDIFF(dd, getdate(), DATEADD(yyyy,
DATEDIFF(yyyy, birthdate, getdate()) + 1, birthdate)) + 1) % 366 <= <number of days>
edición 10/2017: agregue un solo día para finalizar
Mejor y fácil solución:
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
Meses de cumpleaños actuales
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)
Mi suposición es que usar "365.25" tarde o temprano sería un error.
Así que pruebo la solución de trabajo con "365.25" Y no devuelve el mismo número de filas para cada caso. Aquí un ejemplo:
http://sqlfiddle.com/#!3/94c3ce/7
prueba con el año 2016 y 2116 y verás la diferencia. Solo puedo publicar un enlace, pero cambio de / 7 en / 8 para ver ambas consultas. (/ 10 y / 11 para la primera respuesta)
Entonces, sugiero esta otra consulta, donde el punto está determinado el próximo cumpleaños desde una fecha de inicio y luego comparo si está en mi rango de interés.
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
Otro pensamiento: agregue su edad en años completos a su cumpleaños (u otra más si su cumpleaños aún no ha sucedido y luego compare como lo hace arriba. Use DATEPART y DATEADD para hacer esto).
http://msdn.microsoft.com/en-us/library/ms186819.aspx
El caso límite de un rango que abarca el año debería tener un código especial.
Consejo de bonificación: considere usar ENTRE ... Y en lugar de repetir el operando de Cumpleaños.
Próximos cumpleaños para el empleado - 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)
Prueba esto:
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)
Puede usar DATE_FORMAT para extraer el día y el mes de las fechas de cumpleaños.
EDITAR: lo siento, no vi que no estaba usando MySQL.
Puede usar la función DAYOFYEAR
, pero tenga cuidado cuando quiera buscar cumpleaños en enero en diciembre. Creo que estarás bien siempre y cuando el rango de fechas que estás buscando no abarque el Año Nuevo.
Suponiendo que se trata de T-SQL, use DATEPART para comparar el mes y la fecha por separado.
http://msdn.microsoft.com/en-us/library/ms174420.aspx
Alternativamente, reste el 1 de enero del año actual del cumpleaños de todos, y luego compare usando el año 1900 (o lo que sea que sea el año de su época).
También puedes usar 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))
Usé esto para MySQL , probablemente no sea la forma más eficiente de consultar, pero lo suficientemente simple como para implementarlo.
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'');
seleccione BirthDate, nombre de empleados orden por caso CUANDO conversión (nvarchar (5), fecha de nacimiento, 101)> convertir (nvarchar (5), GETDATE (), 101) luego 2 WHEN convert (nvarchar (5), BirthDate, 101) < convert (nvarchar (5), GETDATE (), 101) luego 3 WHEN convert (nvarchar (5), BirthDate, 101) = convert (nvarchar (5), GETDATE (), 101) luego 1 else 4 end, convert (nvarchar (2), BirthDate, 101), convert (nvarchar (2), BirthDate, 105)
Nota: He editado esto para corregir lo que creo que fue un error significativo. La versión publicada actualmente funciona para mí.
Esto debería funcionar después de modificar los nombres de campo y tabla para que se correspondan con su base de datos.
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))
Básicamente, obtiene el número de días desde su cumpleaños hasta ahora, y lo divide por 365 (para evitar problemas de redondeo que surgen cuando se convierte directamente a años).
Luego obtiene el número de días desde su cumpleaños hasta una semana a partir de ahora, y lo divide por 365 para obtener su edad a la semana a partir de ahora.
Si su fecha de nacimiento es dentro de una semana, la diferencia entre esos dos valores será 1. Por lo tanto, devuelve todos esos registros.
Prueba mi solución ... Tengo la base de datos Informix ...
SELECT person, year(today)-year(birthdate) as years, birthdate,
CASE
WHEN MOD(year(birthdate)+((year(today)-year(birthdate))+1),4)<>0 AND MONTH(birthdate)=2 AND DAY(birthdate)=29 THEN
CASE
WHEN mdy(month(birthdate), 28, year(birthdate)+((year(today)-year(birthdate))+1))-today >= 365 THEN (mdy(month(birthdate), 28, year(birthdate)+((year(today)-year(birthdate))+1))-today)-365
WHEN mdy(month(birthdate), 28, year(birthdate)+((year(today)-year(birthdate))+1))-today < 365 THEN mdy(month(birthdate), 28, year(birthdate)+((year(today)-year(birthdate))+1))-today
END
ELSE
CASE
WHEN mdy(month(birthdate), day(birthdate), year(birthdate)+((year(today)-year(birthdate))+1))-today >= 365 THEN (mdy(month(birthdate), day(birthdate), year(birthdate)+((year(today)-year(birthdate))+1))-today)-365
WHEN mdy(month(birthdate), day(birthdate), year(birthdate)+((year(today)-year(birthdate))+1))-today < 365 THEN mdy(month(birthdate), day(birthdate), year(birthdate)+((year(today)-year(birthdate))+1))-today
END
END until
FROM table_name
WHERE mdy(month(birthdate), day(birthdate), 2000) >= mdy(month(today), day(today), 2000)
AND mdy(month(birthdate), day(birthdate), 2000) <= mdy(month(today), day(today), 2000)+30
OR
mdy(month(birthdate), day(birthdate), 2000) <= mdy(month(today), day(today), 2000)-(365-30)
ORDER BY 4, YEAR(birthdate)