I'm currently building a query which needs to show data from Saturday to Friday. For example, running the query today you should get data from 7/24 to 7/30. I’m seeing data from 7/25 to 7/30 and I frankly don’t know how to fix the code below to get Saturday’s data as well.
Here’s what I have:
WHERE
InvoiceDate BETWEEN DATEADD(WEEK, -2, DATEADD(WEEK, DATEDIFF(WEEK, 5, GETDATE()), 5))
AND DATEADD(DAY, -3, DATEADD(WEEK, DATEDIFF(WEEK, 0, GETDATE()), 0))
Preferably, I’d like to keep the similar format rather than parameterizing the query. Unless that’s a better idea of course! I’m also asking this on my phone so I apologize for not including the entire query. However because it is in the where clause, I figured the rest wasn’t needed.
you're leaving out a lot of information so assuming that you are running this query every Monday (as of my reply, today is Monday) and you are just going back to last-last Saturday to last Friday, your WHERE clause can be quite simple:
where InvoiceDate between dateadd(day,-9,getdate()) and dateadd(day,-3,getdate())
if there are are more criteria or conditions then let us know.
try the following query, just put the date whenever you need
SELECT
case
when datepart(weekday, '2021/08/03') >5
then DATEADD(DAY, +4, DATEADD(WEEK, DATEDIFF(WEEK, 0, '2021/08/03'), 0))
else DATEADD(DAY, -9, DATEADD(WEEK, DATEDIFF(WEEK, 0, '2021/08/03'), 0))
end AS last_saturday,
case
when datepart(weekday, '2021/08/03') >5
then DATEADD(DAY, +4, DATEADD(WEEK, DATEDIFF(WEEK, 0, '2021/08/03'), 0))
else DATEADD(DAY, -3, DATEADD(WEEK, DATEDIFF(WEEK, 0, '2021/08/03'), 0))
end AS last_friday;
I realize you have an answer already, but this will allow you to use whatever date you want. Using the day of the week to subtract days from today will give you the previous Saturday. Subtracting 7 from that will give you the Saturday a week ago.
So given that, the below will search the range from the start of a week ago Saturday until the start of this previous Saturday. This works with both date and datetime data types.
WHERE InvoiceDate >= DATEADD(day, -7 + DATEPART(dw,GETDATE()) * -1, GETDATE())
AND InvoiceDate < DATEADD(day, DATEPART(dw,GETDATE()) * -1, GETDATE())
Related
I have the following Where clause in several queries. This successfully retrieves the past months data. Now the year has changed, the query can't find any data (December 2018 hasn't happened yet!). How can I change the Where clause to overcome this?
select *
from somedatabase a
WHERE DATEPART(m, a.meetDate) = DATEPART(m, DATEADD(m, -1, getdate()))
and DATEPART(yyyy, a.meetDate) = DATEPART(yyyy, getdate())
Many thanks and any assistance very gratefully received.
My normal way of rounding down to the start of the current month is:
DATEADD(month, DATEDIFF(month, 0, getDate()), 0)
Find out how many whole months there have been since date 0
Then add that many months to date 0
Always gives the start of the month (as date 0 is the start of a month)
Is not affected by leap year, year boundaries, months of various length, etc
This then allows me to do things like...
WHERE
a.meetDate >= DATEADD(month, DATEDIFF(month, 0, getDate()) - 1, 0) -- start of last month
AND a.meetDate < DATEADD(month, DATEDIFF(month, 0, getDate()) , 0) -- start of this month
By having the calculations on the right hand side you make maximum use of indexes.
Here is one way:
WHERE DATEPART(month, a.meetDate) = DATEPART(month, DATEADD(m, -1, getdate())) AND
DATEPART(year, a.meetDate) = DATEPART(year, DATEADD(m, -1, getdate()))
That is, subtract one month for both comparisons.
Actually, a simpler way is to use the strange rules of DATE_DIFF():
WHERE DATEDIFF(month, a.meetDate, getdate()) = 1
Neither of these can make use of an index. For that, the expression is a little more complicated:
WHERE a.meetDate >= DATEFROMPARTS(YEAR(DATEADD(MONTH, -1, GETDATE()),
MONTH(DATEADD(MONTH, -1, GETDATE()),
1) AND
a.meetDate < DATEADD(DAY, 1 - DAY(GETDATE()), CAST(GETDATE() as DATE))
When I run this where clause on my table I get 2 different results and to me its seems like I should get the same number of records back.
The one I'm using just a static date to test and the other should also retrieve the same results where I'm trying to get last month results
I idea the query is a report that will automatic load the previous months records.
WHERE
(OrderReceiptedDate >= '2015-03-01')
AND (OrderReceiptedDate <= '2015-03-31')
WHERE
(DATEPART(mm, OrderReceiptedDate) = DATEPART(mm, DATEADD(mm, - 1, GETDATE())))
AND
(DATEPART(yy, OrderReceiptedDate) = DATEPART(yy, DATEADD(mm, - 1, GETDATE())))
These are the two statements
WHERE (OrderReceiptedDate >= '2015-03-01' AND
OrderReceiptedDate <= '2015-03-31'
)
WHERE (DATEPART(month, OrderReceiptedDate) = DATEPART(month, DATEADD(month, - 1, GETDATE()))) AND
(DATEPART(year, OrderReceiptedDate) = DATEPART(year, DATEADD(month, - 1, GETDATE())))
Given that today is April 2015, you are expecting that both of these get all dates for March. And, they would, if your dates had no time components. The problem is that almost any datetime on March 31st is not going to match the first condition. The one exception is exactly at midnight: 2015-03-01 00:00:00.000.
The first is better written as:
WHERE (OrderReceiptedDate >= '2015-03-01' AND
OrderReceiptedDate < '2015-04-01'
)
A better way to write "get me last months date" is something like:
WHERE OrderReceiptedDate >= dateadd(month, -1, cast(getdate() - day(getdate()) + 1 as date)) and
OrderReceiptedDate < cast(getdate() - day(getdate()) + 1 as date)
This does all the calculations on getdate() so the query could still take advantage of an index on OrderReceiptDate.
I have a database with a date column that logs when a new "contact" is created. The contacts are generated when the call center receives a new call or e-mail.
What I want is for the where clause to capture the last 13 months of full data.
Examples:
Today is 1/30/2015, if executed the query would return records from 12/1/2013 to 12/31/2014.
Today is 2/06/2015, if executed the query would return records from 1/1/2014 to 1/31/2015.
The query will include those dates falling on the first and last days of the month.
The code I have is as follows:
WHERE
dbo.ub_contact.contact_dt BETWEEN DATEADD(year, -1, (DATEADD(month, DATEDIFF(month, -1, getdate()) - 1, -1) + 1))
AND DATEADD(month, DATEDIFF(month, -1, getdate()) - 1, -1)
Ran today (1/30/2015) this code seems to be returning 1/1/2014 - 12/31/2014.
I would appreciate any help toward getting this worked out.
Thanks!
John
Use this dates:
SELECT EOMONTH(DATEADD(mm, -1, GETDATE()))
SELECT DATEADD(dd, 1, EOMONTH(DATEADD(mm, -14, GETDATE())))
So you where clause would look like:
WHERE dbo.ub_contact.contact_dt BETWEEN DATEADD(dd, 1, EOMONTH(DATEADD(mm, -14, GETDATE()))) AND EOMONTH(DATEADD(mm, -1, GETDATE()))
I have to collect all the rows in a table where they were inserted on a Monday for the last 3 three months. How would I write the WHERE clause date to get those results?
WHERE Date = (wk, DATEDIFF(wk,0,GETDATE()), 0)
That will select everything from Monday of the current week, but what I am having a problem with is selecting a range of Mondays going back three months.
thanks!
So this is the WHERE clause I ended up with that works well for me....
where Datestamp > dateadd(month, -3, getdate())
AND datepart(weekday, Datestamp) = datepart(weekday, DATEADD(wk, DATEDIFF(wk,0,GETDATE()), 0))
I changed only the part where we enter the day of the week that starts on Monday I added this...
DATEADD(wk, DATEDIFF(wk,0,GETDATE()), 0)
WHERE Date > dateadd(month, -3, getdate())
AND datepart(weekday, Date) = 1
These are two separate conditions; no need to compress them into one.
Note: run a test on your machine to see which value you get for datepart(weekday, #AMondayDate). On some systems Monday is 1, on others is 2; it depends on the DATEFIRST configuration.
Update:
Thanks to ErikE for the clever trick that overcomes the weekday numbers issue:
WHERE Date > dateadd(month, -3, getdate())
AND datepart(weekday, Date) = datepart(weekday, '2012-11-25')
Currently one of the reports reads the month_ref which is created like this:
((DATEPART(yy, month_date) - 1200) * 100) + DATEPART(mm, month_date) AS month_ref,
month_date, DATENAME(MONTH, month_date) + ' ' + DATENAME(YEAR, month_date) AS month_name
I would like to create something like a week_ref?
The month ref uniqely identifies the month for the year. When its passed into a particular stored procedure, the sp will filter the results based on the month ref.
I am now wanting to create a weekly report - (mon - sun) and need to uniquely identify the week_ref so i can filter the results using the sp.
How can i do this?
This will give you a unique number for each week from monday to sunday and it doesn't depend on datefirst.
SELECT datediff(day, 0, month_date) / 7 week_ref FROM <table>
This will return an integer always as tested here:
SELECT SQL_VARIANT_PROPERTY(datediff(day, 0, getdate()) / 7, 'BaseType')
Returns:
int
Although I'd consider this technique very dirty, for months it does work. This is because there are always 12 months in a year.
For weeks it's both dirty and flawed. Some years have more weeks than others, because some weeks span more than one year.
I would recommend instead just using DATEDIFF().
Depending on the day-of-week that you want your weeks to start on, you need to do a little bit of calculation...
- Sun as start of week = DATEDIFF(WEEK, -1, yourDate )
- Mon as start of week = DATEDIFF(WEEK, -1, yourDate-1)
- Tue as start of week = DATEDIFF(WEEK, -1, yourDate-2)
- Wed as start of week = DATEDIFF(WEEK, -1, yourDate-3)
- Thu as start of week = DATEDIFF(WEEK, -1, yourDate-4)
- Fri as start of week = DATEDIFF(WEEK, -1, yourDate-5)
- Sat as start of week = DATEDIFF(WEEK, -1, yourDate-6)
I also recommend using this for your month calculations. DATEDIFF(MONTH, <a base date>, <your date>), the current one is really clunky.
EDIT Examples to turn the values above back into DATETIME
- Sun as start of week = DATEADD(WEEK, DATEDIFF(WEEK, -1, yourDate ), -1 )
- Mon as start of week = DATEADD(WEEK, DATEDIFF(WEEK, -1, yourDate-1), -1+1)
- Tue as start of week = DATEADD(WEEK, DATEDIFF(WEEK, -1, yourDate-2), -1+2)
- Wed as start of week = DATEADD(WEEK, DATEDIFF(WEEK, -1, yourDate-3), -1+3)
- Thu as start of week = DATEADD(WEEK, DATEDIFF(WEEK, -1, yourDate-4), -1+4)
- Fri as start of week = DATEADD(WEEK, DATEDIFF(WEEK, -1, yourDate-5), -1+5)
- Sat as start of week = DATEADD(WEEK, DATEDIFF(WEEK, -1, yourDate-6), -1+6)
Use
Select DATEPART(wk, GetDate()) --In your case month_date and not GetDate()
to get the week of the year back, and then you can use any formula you like to create a week_ref, but from what I can see from your edit, this whould the only thing that you need. However, you would change your month_ref to something like this.
((DATEPART(yy, month_date) - 1200) * 10000) + (DATEPART(mm, month_date) * 100) + DATEPART(wk, month_date) AS month_ref
Then you don't have to add an extra column
Use a calendar table with (at least) 3 columns: base_date, month_ref and week_ref. Then to get the month and week references (whatever those are) for a certain date, you can query them directly from the calendar table without using hard-to-read nested functions or other 'non-obvious' code:
select week_ref, month_ref
from dbo.calendar
where base_date = #my_date
You haven't explained what week_ref and month_ref actually mean, but if they are just numbers then a calendar table has the significant advantage that it can support mutliple different definitions. For example, you might want to support both the ISO week number and your own, internal week number scheme. You can also easily change values in the table if your logic changes, without changing any code.
As a general observation, a calendar table is usually a better solution than inline functions, especially if your requirements involve reporting.