I have the following Where clause which is causing me issues and I am looking for a work around.
#startDate is the todays date and #endDate is the end date which could be 7 days, 14 days or 20 days in the future, this works fine unless the end month is greater than the start month.
ISSUE- if the StartDate DAY is 20 and the END Date Day is in the next Month example Start Day is 10/21 and End Day is 11/5 than the where clause cancels its self out, I can't use a Between because we are not including the yr.
I tried an OR but this also doesn't work.
WHERE DAY(t.AnniversaryDate) >= DAY(#startDate)
AND DAY(t.AnniversaryDate) <= DAY(#endDate)
AND MONTH(t.AnniversaryDate) >= MONTH(#startDate)
AND MONTH(t.AnniversaryDate) <= MONTH(#endDate)
AND YEAR(t.AnniversaryDate) < YEAR(GETDATE())
The expression
select DATEADD(year,DATEDIFF(year,'19780517',GETDATE()),'19780517')
Will always return the 17th of May of the current year. A similar expression can be used to perform the same trick for any date1 by replacing both instances of '19780517' with the date of interest.
So, whatever "I can't use a Between because we are not including the yr" means, you should be able to work around it by using the above expression.
So, I think what you want would be:
WHERE DATEADD(year,
DATEDIFF(year,t.AnniversaryDate,GETDATE()),
t.AnniversaryDate)
BETWEEN #startDate and #endDate
1So long as you're happy that 29th February maps to 28th February if you ask for it in a non-leap year.
Related
How can I get this week's monday's date in PostgreSQL?
For example, today is 01/16/15 (Friday). This week's monday date is 01/12/15.
You can use date_trunc() for this:
select date_trunc('week', current_date);
More details in the manual:
http://www.postgresql.org/docs/current/static/functions-datetime.html#FUNCTIONS-DATETIME-TRUNC
If "today" is Monday it will return today's date.
SELECT current_date + cast(abs(extract(dow FROM current_date) - 7) + 1 AS int);
works, although there might be more elegant ways of doing it.
The general idea is to get the current day of the week, dow, subtract 7, and take the abs, which will give you the number of days till the end of the week, and add 1, to get to Monday. This gives you next Monday.
EDIT: having completely misread the question, to get the prior Monday, is much simpler:
SELECT current_date - ((6 + cast(extract(dow FROM current_date) AS int)) % 7)
ie, subtract the current day of the week from today's date (the number of day's past Monday) and add one, to get back to Monday.
And for other mondays:
Next Monday:
date_trunc('week', now())+ INTERVAL '7days'
Last week's monday:
date_trunc('week', now())- INTERVAL '7days'
etc. :)
I usually use a calendar table. There are two main advantages.
Simple. Junior devs can query it correctly with little training.
Obvious. Correct queries are obviously correct.
Assuming that "this week's Monday" means the Monday before today, unless today is Monday then . . .
select max(cal_date) as previous_monday
from calendar
where day_of_week = 'Mon'
and cal_date <= current_date;
I have tried the following:
add_months(to_Date('04/01/ind.birth_dte','MM/DD/YYYY'), 864) >= to_date('&StartDt','MM/DD/YYYY')
Is there a better way to pull April first of the participant's 72nd birth date?
You could use an interval calculation instead, but not sure how you're defining 'better'. Assuming you do want April 1st of the year in which their 72 birthday falls:
trunc(ind.birth_dte, 'YYYY') + interval '72-3' year to month
The trunc() function goes to the first day of their birth year, and the interval adds 72 years and 3 months to that, which will be April 1st.
SQL Fiddle with some sample dates, including a leap day to show that isn't a problem.
Or to compare that adjusted date with a fixed date as a filter:
where trunc(ind.birth_dte, 'YYYY') + interval '72-3' year to month
> to_date('&StartDt','MM/DD/YYYY');
SQL Fiddle.
You can use the trunc() method with your version as well to save building up a string and calling to_date, adding an additional three months to the add_months call (though I'd suggest you at least need a comment indicating where '867' comes from):
where add_months(trunc(ind.birth_dte, 'YYYY'), 867)
> to_date('&StartDt','MM/DD/YYYY');
NEWBIE at work! I am trying to create a simple summary that counts the number of customer visits and groups by 1) date and 2) hour, BUT outputs this:
Date Day of Wk Hour #visits
8/12/2013 Monday 0 5
8/12/2013 Monday 1 7
8/12/2013 Monday 6 10
8/13/2013 Tuesday 14 25
8/13/2013 Tuesday 16 4
We are on military time, so 14 = 2:00 pm
Select
TPM300_PAT_VISIT.adm_ts as [Date]
,TPM300_PAT_VISIT.adm_ts as [Day of Week]
,TPM300_PAT_VISIT.adm_ts as [Hour]
,count(TPM300_PAT_VISIT.vst_ext_id) as [Total Visits]
From
TPM300_PAT_VISIT
Where
TPM300_PAT_VISIT.adm_srv_cd='22126'
and TPM300_PAT_VISIT.adm_ts between '07-01-2013' and '08-01-2013'
Group by
cast(TPM300_PAT_VISIT.adm_ts as DATE)
,datepart(weekday,TPM300_PAT_VISIT.adm_ts)
,datepart(hour,TPM300_PAT_VISIT.adm_ts)
Order by
CAST(TPM300_PAT_VISIT.adm_ts as DATE)
,DATEPART(hour,TPM300_PAT_VISIT.adm_ts)
This should solve the problem:
; With Streamlined as (
SELECT
DATEADD(hour,DATEDIFF(hour,'20010101',adm_ts),'20010101') as RoundedTime,
vst_ext_id
from
TPM300_PAT_VISIT
where
adm_srv_cd='22126' and
adm_ts >= '20130701' and
adm_ts < '20130801'
)
Select
CONVERT(date,RoundedTime) as [Date],
DATEPART(weekday,RoundedTime) as [Day of Week],
DATEPART(hour,RoundedTime) as [Hour],
count(vst_ext_id) as [Total Visits]
From
Streamlined
Group by
RoundedTime
Order by
CONVERT(date,RoundedTime),
DATEPART(hour,RoundedTime)
In the CTE (Streamlined)'s select list, we floor each adm_ts value down to the nearest hour using DATEADD/DATEDIFF. This makes the subsequent grouping easier to specify.
We also specify a semi-open interval for the datetime comparisons, which makes sure we include everything in July (including stuff that happened at 23:59:59.997) whilst excluding events that happened at midnight on 1st August. This is frequently the correct type of comparison to use when working with continuous data (floats, datetimes, etc), but means you have to abandon BETWEEN.
I'm also specifying the dates as YYYYMMDD which is a safe, unambiguous format. Your original query could have been interpreted as either January 7th - January 8th or 1st July - 1st August, depending on the settings of whatever account you use to connect to SQL Server. Better yet, if these dates are being supplied by some other (non-SQL) code, would be for them to be passed as datetimes in the first place, to avoid any formatting issues.
The MS SQL DateDiff function counts the number of boundaries crossed when calculating the difference between two dates.
Unfortunately for me, that's not what I'm after. For instance, 1 June 2012 -> 30 June 2012 crosses 4 boundaries, but covers 5 weeks.
Is there an alternative query that I can run which will give me the number of weeks that a month intersects?
UPDATE
To try and clarify exactly what I'm after:
For any given month I need the number of weeks that intersect with that month.
Also, for the suggestion of just taking the datediff and adding one, that won't work. For instance February 2010 only intersects with 4 weeks. And the DateDiff calls returns 4, meaning that simply adding 1 would leave me the wrong number of weeks.
Beware: Proper Week calculation is generally trickier than you think!
If you use Datepart(week, aDate) you make a lot of assumptions about the concept 'week'.
Does the week start on Sunday or Monday? How do you deal with the transition between week 1 and week 5x. The actual number of weeks in a year is different depending on which week calculation rule you use (first4dayweek, weekOfJan1 etc.)
if you simply want to deal with differences you could use
DATEDIFF('s', firstDateTime, secondDateTime) > (7 * 86400 * numberOfWeeks)
if the first dateTime is at 2011-01-01 15:43:22 then the difference is 5 weeks after 2011-02-05 15:43:22
EDIT: Actually, according to this post: Wrong week number using DATEPART in SQL Server
You can now use Datepart(isoww, aDate) to get ISO 8601 week number. I knew that week was broken but not that there was now a fix. Cool!
THIS WORKS if you are using monday as the first day of the week
set language = british
select datepart(ww, #endofMonthDate) -
datepart(ww, #startofMonthDate) + 1
Datepart is language sensistive. By setting language to british you make monday the first day of the week.
This returns the correct values for feburary 2010 and june 2012! (because of monday as opposed to sunday is the first day of the week).
It also seems to return correct number of weeks for january and december (regardless of year). The isoww parameter uses monday as the first day of the week, but it causes january to sometimes start in week 52/53 and december to sometimes end in week 1 (which would make your select statement more complex)
SET DATEFIRST is important when counting weeks. To check what you have you can use select ##datefirst. ##datefirst=7 means that first day of week is sunday.
set datefirst 7
declare #FromDate datetime = '20100201'
declare #ToDate datetime = '20100228'
select datepart(week, #ToDate) - datepart(week, #FromDate) + 1
Result is 5 because Sunday 28/2 - 2010 is the first day of the fifth week.
If you want to base your week calculations on first day of week is Monday you need to do this instead.
set datefirst 1
declare #FromDate datetime = '20100201'
declare #ToDate datetime = '20100228'
select datepart(week, #ToDate) - datepart(week, #FromDate) + 1
Result is 4.
Here is the Query I am using:
SELECT * FROM ra_ProjectCalendar
WHERE MonthNumber between #Month and #Month + 12 and FullYear = #Year
It works great for this year, but, stops at December of this year. How do I get it to show a running year?
how is your date stored?
from your sql, i guess that you have one field for month, one for year and one for day. i'd recommend having one single datetime field instead, and then you can use the DateAdd() method to add 12 months (or any other interval).
EDIT: it was pointed out to me in a comment that one thing you gain on this is performance - which is more or less important depending on the scale of your applicaiton, but always nice to be aware of. if you run this query in a stored procedure, here's what you'll do:
DECLARE #oneYearAhead datetime;
SET #oneYearAhead = DateAdd(m, 12, #PassedDate)
SELECT * FROM ra_ProjectCalendar
WHERE #PassedDate <= [Date] AND [Date] <= #oneYearAhead;
with the above code, you will get all entries between the date you pass, and one year ahead of it. (i am not 100% sure on the syntax to declare and set the #oneYearAhead variable, but you get the idea...). Note that the [] that i use around the column name Date allows me to use reserved words in column names - i have made it a habit, instead of memorizing which words are reserved...
Try this:
SELECT * FROM ra_ProjectCalendar
WHERE
(MonthNumber > #Month AND FullYear = #Year)
OR (MonthNumber < #Month AND FullYear = #Year + 1)
Something like this might work better - but its not clear what your intent is:
select *
from ra_ProjectCalendar
where DATEDIFF ( month , #startdate , #enddate ) <=12
Edit: This is SQl server syntax
Actually pass in and store the date rather than month and year, and compare with the current date using DateDiff:
WHERE DATEDIFF(m, #PassedDate, StoredDateColumn) < 12
Note that I used 12 months, rather than 1 year, because DATEDIFF counts the number of boundries crossed. So in december, using datediff with the year datepart would return one after only one month. You really want a 12 month span.
Depending on how your information is stored (it's a little difficult to tell from your query), either DATEADD or DATEDIFF will probably do you right. There's a list of the availabe date functions on MSDN.