Exclude weekends from my query - sql

I have a query which is working fine.
The query basically retrieves data between 6-8 days old from current date. I'd like exclude the weekends when measuring the age of the data.
Example: If a record is registered Friday, then Monday morning it will show like it's 4 days old, but it's actually only 2 days old, because Satuday and Sunday shouldn't count.
I tried this, which does not seem to be working:
Select id, name, CreatedDate
from table
where
CreatedDate <= DATEADD(day, -6, GETDATE()) AND CreatedDate >= DATEADD(day, -8, GETDATE()) -- here I get data between 6-8 days old
AND ((DATEPART(dw, CreatedDate) + ##DATEFIRST) % 7) NOT IN (0, 1) -- Here im trying to exclude weekends
What am I doing wrong?

You could see calendar and try this query
// Logic is very simple.
// See calendar and try.
// If today is Monday, then Prev8workingdays will include
// 8 working days + 2 weekends = 12 days.
// Then result will be dateadd(day,-12, getdate()) = 12 days before today.
// Same logic for other days week
DECLARE #Prev8workingdays date = CASE
WHEN datepart(dw, getdate()) IN (2,3,4) THEN dateadd(day,-12, getdate())
WHEN datepart(dw, getdate()) IN (1) THEN dateadd(day,-11, getdate())
ELSE dateadd(day,-10, getdate())
END
DECLARE #Pre6WorkingDay date = CASE
WHEN datepart(dw, getdate()) IN (2) THEN dateadd(day,-10, getdate())
WHEN datepart(dw, getdate()) IN (1) THEN dateadd(day,-9, getdate())
ELSE dateadd(day,-8, getdate())
END
SELECT sd.* FROM
#SampleDate sd
WHERE sd.CreatedDate >= #Prev8workingdays AND sd.CreatedDate <= #Pre6WorkingDay
Reference link DATEADD

you can try:
WHERE DATEPART(dw, date_created) NOT IN (1, 7);

Try this:
Select id, name, CreatedDate
from table
where CreatedDate < GETDATE()-6 and CreatedDate > GETDATE()-8 and
((DATEPART(dw, CreatedDate) + ##DATEFIRST) % 7) NOT IN (0, 1)

Related

Data for last week from Monday to Sunday- Available data is Datetime column

I have column date time available in following format
'2022-02-28 08:30:08.000"
I would like run a SQL query to help me get data for last week from Monday to Sunday basis ongoing
Please help
You can try to play around with DATEPART
Below script should return all data for current week.
-- below line will set Monday as first day of the week
set datefirst 1;
SELECT *
FROM YOUR_TABLE
WHERE DATEPART(ISOWK, YOUR_COLUMN) = DATEPART(ISOWK, GETDATE())
AND DATEPART(YEAR, YOUR_COLUMN) = DATEPART(YEAR, GETDATE())
Below should return data for whole previous week...
set datefirst 1;
SELECT *
FROM YOUR_TABLE
WHERE DATEPART(ISOWK, YOUR_COLUMN) = DATEPART(ISOWK, DATEADD(DAY, -7, GETDATE()))
AND DATEPART(YEAR, YOUR_COLUMN) = DATEPART(YEAR, DATEADD(DAY, -7, GETDATE()))

Convert iso_week to calendar date in SQL

I've been searching though the archives without finding what I am looking for- I'd be happy for some guidance.
I have a data set where I want to report aggregated number of appointments by provider (STAFFID) and work week, the latter defined by the week's Monday date. I've played with datepart(iso_week, appointment_date) as week_of_yr which gets me part of the way there- I can group by week to get the right numbers. However, I can't figure out if there's a simple way to display the date of the week's Monday given the iso_week integer (and year).
I found ISO8601 Convert Week Date to Calendar Date helpful, though I do not know whether (or how) I can automate that process for many values at once.
Here's the tidbit of code I have. Ideally I could add another expression to the select statement which would display the desired date.
select STAFFID
, count(*) as appointment_ct
, datepart(iso_week, appointment_date) as iso_wk --this returns the week # of the year as an int
from [dbo].[view_APPT_DATA]
where program_code in ('99999')
and appointment_date >= '1/1/2016' and appointment_date <='3/31/2016'
group by iso_wk, STAFFID
I would find the first Monday of that year and then use DATEADD to add the number of weeks to that day
select STAFFID
, count(*) as appointment_ct
, datepart(iso_week, appointment_date) as iso_wk --this returns the week # of the year as an int
, dateadd(week, datepart(week, DATEADD(DAY, (##DATEFIRST - DATEPART(WEEKDAY, dateadd(year, datepart(year, appointment_date) - 1900, 0)) + (8 - ##DATEFIRST) * 2) % 7, dateadd(year, datepart(year, appointment_date) - 1900, 0))) as monday_wk
from [dbo].[view_APPT_DATA]
where program_code in ('99999')
and appointment_date >= '1/1/2016' and appointment_date <='3/31/2016'
group by iso_wk, STAFFID, monday_wk
I didn't quite get the cha's query to return correct results for "special" years that have overlapping weeks.
This is the (inline) function i ended up with to calculate iso week to first day of that week:
CREATE OR ALTER FUNCTION dbo.FN_ISOWEEK_TO_DAY (
-- ISOWeek in format YYYYWW
#pISOWeek INT
)
RETURNS TABLE AS RETURN
SELECT DATEADD(week, CAST(RIGHT(#pISOWeek, 2) AS INT) - 1
- CASE WHEN (##DATEFIRST - DATEPART(WEEKDAY, DATEADD(YEAR, cast(LEFT(#pISOWeek, 4) AS INT) - 1900, 0)) + (8 - ##DATEFIRST) * 2) % 7 >= 4 -- means first monday is one week ahead
THEN 1 ELSE 0 END
, DATEADD(DAY, (##DATEFIRST - DATEPART(WEEKDAY, DATEADD(YEAR, cast(LEFT(#pISOWeek, 4) AS INT) - 1900, 0)) + (8 - ##DATEFIRST) * 2) % 7, DATEADD(YEAR, cast(LEFT(#pISOWeek, 4) AS INT) - 1900, 0)))
AS firstDay
Some test code:
SELECT *
FROM (
SELECT 202001, 20191230
UNION ALL
SELECT 202053, 20201228
) x (dt, expectedValue)
CROSS APPLY dbo.FN_ISOWEEK_TO_DAY(x.dt) y

default date value of every Friday in SQL Server?

In SQL Server 2008 i want to set a default date value of every Friday to show up in the column when i insert a new record?
ALTER TABLE myTable ADD CONSTRAINT_NAME DEFAULT GETDATE() FOR myColumn
Whats the best way to show every Friday?
I want the default value to be based on the now date then knowing that the next available date is 05-07/2013
I have the following:
dateadd(d, -((datepart(weekday, getdate()) + 1 + ##DATEFIRST) % 7), getdate())
But when passing todays date, it gave me: 2013-06-28 which is actually LAST Friday!, it should be the up and coming Friday!
SELECT DATEADD(day,-3, DATEADD(week, DATEDIFF(week, 0, current_timestamp)+1, 0)) AS LastFridayDateOfWeek
Gets the last date of current week (sunday) then subtracts 3 from that to get Friday.
Replace current_timestamp if you need a different dates friday.
EDIT:
I thought about this a bit, and if the above (Friday THIS WEEK, so for Saturday it gives the previous date) does not work, you could easily use a reference date set like so:
DATEADD(DAY,7 + DATEDIFF(day,'20100109',#checkDateTime)/7*7,'20100108') as FridayRefDate
Same thing but with no hard coded Friday/Saturday in it:
DATEADD(DAY,7 + DATEDIFF(day,DATEADD(wk, DATEDIFF(wk,0,#checkDateTime),5),#checkDateTime)/7*7,DATEADD(wk, DATEDIFF(wk,0,#checkDateTime), 4))
So for 20100109 is a Friday.
SET #checkDateTime = '2012-01-14 3:34:00.000'
SELECT DATEADD(DAY,7 + DATEDIFF(day,'20100109',#checkDateTime)/7*7,'20100108') as FridayRefDate
it returns "2012/1/20"
But for SET #checkDateTime = '2012-01-13 3:34:00.000' it returns "2012/1/13"
If your current query gives you last Friday, the easiest thing to do is simply to add 7 to it:
select dateadd(d, 7-((datepart(weekday, getdate()) + 1 + ##DATEFIRST) % 7), getdate())
------------------^
SELECT CONVERT(DATE, ( CASE WHEN DATEPART(dw, GETDATE()) - 6 <= 0
THEN DATEADD(dd,
( DATEPART(dw, GETDATE()) - 6 ) * -1,
GETDATE())
ELSE DATEADD(dd, ( DATEPART(dw, GETDATE()) ) - 1,
GETDATE())
END )) AS NearestFriday
Just add 7 to the formula
SELECT DATEADD(dd,CAST(5-GETDATE() AS int)%7,GETDATE()+7)
To verify the formula:
WITH test AS (
SELECT GETDATE() AS d UNION ALL
SELECT DATEADD(dd,1,d)
FROM test WHERE d < GETDATE() + 30
)
SELECT
d AS [input],
DATEADD(dd,CAST(5-d AS int)%7,d+7) AS [output]
FROM test
To tweak the the formula, adjust the 5- and the +7

Get last Friday's Date unless today is Friday using T-SQL

I'm trying to get the correct SQL code to obtain last Friday's date. A few days ago, I thought I had my code correct. But just noticed that it's getting last week's Friday date, not the last Friday. The day I'm writing this question is Saturday, 8/11/2012 # 12:23am. In SQL Server, this code is returning Friday, 8/3/2012. However, I want this to return Friday, 8/10/2012 instead. How can I fix this code? Since we're getting to specifics here, if the current day is Friday, then I want to return today's date. So if it were yesterday (8/10/2012) and I ran this code yesterday, then I would want this code to return 8/10/2012, not 8/3/2012.
SELECT DATEADD(DAY, -3, DATEADD(WEEK, DATEDIFF(WEEK, 0, GETDATE()), 0))
try this:
declare #date datetime;
set #date='2012-08-09'
SELECT case when datepart(weekday, #date) >5 then
DATEADD(DAY, +4, DATEADD(WEEK, DATEDIFF(WEEK, 0, #date), 0))
else DATEADD(DAY, -3, DATEADD(WEEK, DATEDIFF(WEEK, 0, #date), 0)) end
result:
2012-08-03
Example2:
declare #date datetime;
set #date='2012-08-10'
SELECT case when datepart(weekday, #date) >5 then
DATEADD(DAY, +4, DATEADD(WEEK, DATEDIFF(WEEK, 0, #date), 0))
else DATEADD(DAY, -3, DATEADD(WEEK, DATEDIFF(WEEK, 0, #date), 0)) end
result:
2012-08-10
Modular arithmetic is the most direct approach, and order of operations decides how Fridays are treated:
DECLARE #test_date DATETIME = '2012-09-28'
SELECT DATEADD(d,-1-(DATEPART(dw,#test_date) % 7),#test_date) AS Last_Friday
,DATEADD(d,-(DATEPART(dw,#test_date+1) % 7),#test_date) AS This_Friday
Use this :
SELECT DATEADD(day, (DATEDIFF (day, '19800104', CURRENT_TIMESTAMP) / 7) * 7, '19800104') as Last_Friday
None of that? Try this:
DECLARE #D DATE = GETDATE()
SELECT DATEADD(D,-(DATEPART(W,#D)+1)%7,#D)
A tested function which works no matter what ##DATEFIRST is set to.
-- ==============
-- fn_Get_Week_Ending_forDate
-- Author: Shawn C. Teague
-- Create date: 2017
-- Modified date:
-- Description: Returns the Week Ending Date on DayOfWeek for a given stop date
-- Parameters: DayOfWeek varchar(10) i.e. Monday,Tues,Wed,Friday,Sat,Su,1-7
-- DateInWeek DATE
-- ==============
CREATE FUNCTION [dbo].[fn_Get_Week_Ending_forDate] (
#DayOfWeek VARCHAR(10),#DateInWeek DATE)
RETURNS DATE
AS
BEGIN
DECLARE #End_Date DATE
,#DoW TINYINT
SET #DoW = CASE WHEN ISNUMERIC(#DayOfWeek) = 1
THEN CAST(#DayOfWeek AS TINYINT)
WHEN #DayOfWeek like 'Su%' THEN 1
WHEN #DayOfWeek like 'M%' THEN 2
WHEN #DayOfWeek like 'Tu%' THEN 3
WHEN #DayOfWeek like 'W%' THEN 4
WHEN #DayOfWeek like 'Th%' THEN 5
WHEN #DayOfWeek like 'F%' THEN 6
ELSE 7
END
select #End_Date =
CAST(DATEADD(DAY,
CASE WHEN (#DoW - (((##datefirst) + datepart(weekday, #DateInWeek)) % 7)) = 7
THEN 0
WHEN (#DoW - (((##datefirst) + datepart(weekday, #DateInWeek)) % 7)) < 0
THEN 7 - ABS(#DoW - (((##datefirst) + datepart(weekday, #DateInWeek)) % 7))
ELSE (#DoW - (((##datefirst) + datepart(weekday, #DateInWeek)) % 7) )
END
,#DateInWeek) AS DATE)
RETURN #End_Date
END
This will give you the Friday of Last week.
SELECT DATEADD(day, -3 - (DATEPART(dw, GETDATE()) + ##DATEFIRST - 2) % 7, GETDATE()) AS LastWeekFriday
This will give you last Friday's Date.
SELECT DATEADD(day, +4 - (DATEPART(dw, GETDATE()) + ##DATEFIRST-2) % 7, GETDATE()) AS LastFriday
select convert(varchar(10),dateadd(d, -((datepart(weekday, getdate()) + 1 + ##DATEFIRST) % 7), getdate()),101)
Following code can be use to return any last day by replacing #dw_wk, test case below use friday as asked in original questions
DECLARE #date SMALLDATETIME
,#dw_wk INT --last day of week required - its integer representation
,#dw_day int --current day integer reprsentation
SELECT #date='8/11/2012'
SELECT #dw_day=DATEPART(dw,#date)
SELECT #dw_wk=DATEPART(dw,'1/2/2015') --Just trying not to hard code 5 for friday, here we can substitute with any date which is friday
SELECT case when #dw_day<#dw_wk then DATEADD(DAY, #dw_wk-7-#dw_day,#date) else DATEADD(DAY,#dw_wk-#dw_day, #date) END
Here's an answer I found here adapted from MySQL to T-SQL that is a one liner using all basic arithmetic (no division or modulos):
SELECT DATEADD(d, 1 - datepart(weekday, dateadd(d, 2, GETDATE())), GETDATE())
You can do all sorts of combinations of this, like get next Friday's date unless today is Friday, or get last Thursday's date unless today is Thursday by just changing the 1 and the 2 literals in the command:
Get next Friday's date unless today is Friday
SELECT DATEADD(d, 7 - datepart(weekday, dateadd(d, 1, GETDATE())), GETDATE())
Get last Thursday's date unless today is Thursday
SELECT DATEADD(d, 1 - datepart(weekday, dateadd(d, 3, GETDATE())), GETDATE())
I have had this same issue, and created the following example to show how to do this and to make it flexible to use whichever day of the week you want. I have different lines in the SELECT statement, just to show what this is doing, but you just need the [Results] line to get the answer. I also used variables for the current date and the target day of the week, to make it easier to see what needs to change.
Finally, there is an example of results when you want to include the current date as a possible example or when you always want to go back to the previous week.
DECLARE #GetDate AS DATETIME = GETDATE();
DECLARE #Target INT = 6 -- 6 = Friday
SELECT
#GetDate AS [Current Date] ,
DATEPART(dw, #GetDate) AS [Current Day of Week],
#Target AS [Target Day of Week] ,
IIF(#Target = DATEPART(dw, #GetDate), 'Yes' , 'No') AS [IsMatch] ,
IIF(#Target = DATEPART(dw, #GetDate), 0 , ((7 + #Target - DATEPART(dw, #GetDate)) % 7) - 7) AS [DateAdjust] ,
------------------------------------------------------------------------------------------------------------------------------------------------
CAST(IIF(#Target = DATEPART(dw, #GetDate), #GetDate, DATEADD(d, (((7 + #Target - DATEPART(dw, #GetDate)) % 7) - 7), #GetDate)) AS DATE) AS [Result]
------------------------------------------------------------------------------------------------------------------------------------------------
;
SELECT
#GetDate AS [Current Date] ,
DATEPART(dw, #GetDate) AS [Current Day of Week],
#Target AS [Target Day of Week] ,
((7 + #Target - DATEPART(dw, #GetDate)) % 7) - 7 AS [DateAdjust] ,
------------------------------------------------------------------------------------------------------------------------------------------------
CAST(DATEADD(d, (((7 + #Target - DATEPART(dw, #GetDate)) % 7) - 7), #GetDate) AS DATE) AS [NOTIncludeCurrent]
------------------------------------------------------------------------------------------------------------------------------------------------
;
SELECT DECODE(TO_CHAR(SYSDATE,'DY'),'FRI',SYSDATE,NEXT_DAY(SYSDATE, 'FRI')-7) FROM dual;

SQL Select Upcoming Birthdays

I'm trying to write a stored procedure to select employees who have birthdays that are upcoming.
SELECT * FROM Employees WHERE Birthday > #Today AND Birthday < #Today + #NumDays
This will not work because the birth year is part of Birthday, so if my birthday was '09-18-1983' that will not fall between '09-18-2008' and '09-25-2008'.
Is there a way to ignore the year portion of date fields and just compare month/days?
This will be run every monday morning to alert managers of birthdays upcoming, so it possibly will span new years.
Here is the working solution that I ended up creating, thanks 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: I've edited this to fix what I believe was a significant bug. The currently posted version works for me.
This should work after you modify the field and table names to correspond to your database.
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))
Basically, it gets the # of days from their birthday to now, and divides that by 365 (to avoid rounding issues that come up when you convert directly to years).
Then it gets the # of days from their birthday to a week from now, and divides that by 365 to get their age a week from now.
If their birthday is within a week, then the difference between those two values will be 1. So it returns all of those records.
In case someone is still looking for a solution in MySQL (slightly different commands), here's the query:
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)
Best use of datediff and dateadd. No rounding, no approximates, no 29th of february bug, nothing but date functions
ageOfThePerson = DATEDIFF(yyyy,dateOfBirth, GETDATE())
dateOfNextBirthday = DATEADD(yyyy,ageOfThePerson + 1, dateOfBirth)
daysBeforeBirthday = DATEDIFF(d,GETDATE(), dateofNextBirthday)
Thanks to #Gustavo Cardoso, new definition for the age of the person
ageOfThePerson = FLOOR(DATEDIFF(d,dateOfBirth, GETDATE())/365.25)
Liked the approach of #strelc, but his sql was a bit off. Here's an updated version that works well and is simple to use:
SELECT * FROM User
WHERE (DATEDIFF(dd, getdate(), DATEADD(yyyy,
DATEDIFF(yyyy, birthdate, getdate()) + 1, birthdate)) + 1) % 366 <= <number of days>
edit 10/2017: add single day to end
You could use the DAYOFYEAR function but be careful when you want to look for January birthdays in December. I think you'll be fine as long as the date range you're looking for doesn't span the New Year.
Sorry didn't see the requirement to neutralize the year.
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)
This should work.
My guess is using "365.25" soon or later would be fail.
So I test the working solution using "365.25"
And It don't return the same numbers of rows for every case.
Here an example:
http://sqlfiddle.com/#!3/94c3ce/7
test with year 2016 and 2116 and you will see the difference. I only can post one link but change de /7 by /8 to see both queries. (/10 and /11 for the first answer)
So, I suggest this another query, where the point is determinate next birthday from a starting date and then compare if it is in my range of interest.
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
This is solution for MS SQL Server:
It returns employees with birthdays in 30 days.
SELECT * FROM rojstni_dnevi
WHERE (DATEDIFF (dd,
getdate(),
DATEADD ( yyyy,
DATEDIFF(yyyy, rDan, getdate()),
rDan)
nex )
+365) % 365 < 30
I found the solution for this. This may save someone's precious time.
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
Make a cross join with the dates and check for the comparison of month and dates.
In less than a month:
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() ))))
You could use DATE_FORMAT to extract the day and month parts of the birthday dates.
EDIT: sorry i didn't see that he wasn't using MySQL.
Assuming this is T-SQL, use DATEPART to compare the month and date separately.
http://msdn.microsoft.com/en-us/library/ms174420.aspx
Alternatively, subtract January 1st of the current year from everyone's birthday, and then compare using the year 1900 (or whatever your epoch year is).
Most of these solutions are close, but you have to remember a few extra scenarios. When working with birthdays and a sliding scale, you must be able to handle the transition into the next month.
For example Stephens example works great for birthdays up until the last 4 days of the month. Then you have a logic fault as the valid dates if today was the 29th would be :29, 30, AND then 1, 2, 3 of the NEXT month, so you have to condition for that as well.
An alternative would be to parse the date from the birthday field, and sub in the current year, then do a standard range comparison.
Another thought: Add their age in whole years to their birthday (or one more if their Birthday hasn't happened yet and then compare as you do above. Use DATEPART and DATEADD to do this.
http://msdn.microsoft.com/en-us/library/ms186819.aspx
The edge case of a range spanning the year would have to have special code.
Bonus tip: consider using BETWEEN...AND instead of repeating the Birthday operand.
This should work...
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))
I faced the same problem with my college project a few years ago. I responded (in a rather weasel way) by splitting the year and the date(MM:DD) in two separate columns. And before that, my project mate was simply getting all the dates and programatically going through them. We changed that because it was too inefficient - not that my solution was any more elegant either. Also, its probably not possible to do in a database that has been in use for a while by multiple apps.
Give this a try:
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)
Nuts! A good solution between when I started thinking about this and when I came back to answer. :)
I came up with:
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
You don't need to cast getdate() as a datetime, right?
This is a combination of a couple of the answers that was tested. This will find the next brithday after a certain date and the age they will be. Also the numdays will limit the range you are looking 7 days = week 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
The best way to achieve the same is
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)
Upcoming Birthday for the Employee - 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)
I used this for MySQL, probably not the most efficient way to query but simple enough to implement.
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');
i believe this ticket has been closed ages ago but for the benefit of getting the correct sql query please have a look.
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))
Better and easy solution:
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
I hope this helps u in some way....
select Employeename,DOB
from Employeemaster
where day(Dob)>day(getdate()) and month(DOB)>=month(getDate())
This solution also takes care for birthdays in the next year and the ordering:
(dob = day of birth; bty = birthday this year; nbd = next birthday)
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
This version, which avoids comparison of the dates, could be faster:
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
If the range covers the 29 of February in the next year, then use:
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
You can also use 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))
Below query will return all next birthday of employee, it is shortest query.
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 ;
Above query will cover all next month excluding current date.
Solution for SQLite3:
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
;
The solutions dividing by 325.25 to get the age, or bringing the birthdate to the current year etc. didn't work for me.
What this does is computes the delta of the two daysOfTheYear (1-366). If the birthday didn't happen yet this year, you automatically get the correct number of remaining days, which you can compare to.
If the birthday already happened, remaining_days will be negative, and you can get the correct number of remaining days by still adding the total amount of days in the current year. This also correctly handles leap years, since in that case the extra day will be added as well (By using dayOfYear(Dec 31.))
select BirthDate,Name from Employees
order by Case
WHEN convert(nvarchar(5),BirthDate,101) > convert(nvarchar(5),GETDATE(),101) then 2
WHEN convert(nvarchar(5),BirthDate,101) < convert(nvarchar(5),GETDATE(),101) then 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)