I have a table with results for everyday of the week for the past year. I need to get the average sales based off same day of the week(starting today) for the past 4 weeks. i.e. sales for every monday for the past 4 weeks.
What would be the best route? Any and all advice is greatly appreciated.
Fairly straight forward, the only gotcha could be performance, which is why I'm isolating the the 28 day function so the cutoff date can be a SARG.
declare #cutoffdate datetime = dateadd(day, -28, (DATEADD(dd, DATEDIFF(dd, 0, getdate()), 0)))
select avg(sales) as averagesales
, datepart(dw, saledate) as saleDayOfWeeks
from your table
where saledate >= #cutoffdate
group by datepart(dw, saledate)
Let me know if that doesn't work.
Related
I have a list of employees and their hire dates. I need to pull revenue records for their first 3 months on the job. For example, if someone is hired on August 6 2018, I need to pull their revenue records for September, October, and November 2018.
I really just need the "where" statement to find the correct dates.
Let's call the tables: bookings, employees
columns: hired_at, booked_at
I originally thought it was first 3 months from hire date, and I used
where bookings.booked_at <= dateadd(month, 3, employees.hire_date)
Upon finding out that I need the 3 months FOLLOWING the hire date, I'm not sure how to write this.
Thanks!
You should use INTERVAL, dateadd isn't supported by PostgreSQL
<= employees.hire_date - Interval '3 months'
You can check the documentation in the following link
https://www.postgresql.org/docs/9.0/functions-datetime.html
WHERE booked_at >= date_trunc('month', hired_at + interval '1 month')
AND booked_at < date_trunc('month', hired_at + interval '3 month')
where date_trunc('month', ...) always gives you the 1st of the month.
Sorry if this has been asked somewhere all ready but I've struggled to find the answer! I have a date time field with is a date time stamp on activity.
I need to have a query that only brings back information for data that's between today's date and events between 08:00 and 10:00.My brains says it should be straight forward but i cant suss it.
Thanks
To get a particular point in time, I tend to use the DATEADD/DATEDIFF pattern. It can look a bit unwieldy, but performs quite nicely, and once you're used to seeing it, it becomes more readable:
SELECT * --TODO - Pick columns
FROM Activities
WHERE OccurredAt BETWEEN
DATEADD(day,DATEDIFF(day,'20010101',GETDATE()),'2001-01-01T08:00:00') AND
DATEADD(day,DATEDIFF(day,'20010101',GETDATE()),'2001-01-01T10:00:00')
Here I'm using it twice. It just relies on the relationship between two date constants that you pick because they exhibit the features that you want. So here:
DATEADD(day,DATEDIFF(day,'20010101',GETDATE()),'2001-01-01T08:00:00')
I'm calculating the number of (whole) days that have elapsed between 1st January 2001 and right now. I'm then adding that (whole) number of days onto 08:00 on the 1st January 2001 - which will, logically, produce 08:00 today.
Here you go...
SELECT * FROM <TABLE_NAME> WHERE EVENTS_DATE BETWEEN
DATEADD(hour, 8, DATEADD(day, DATEDIFF(day, 0, GETDATE()), 0))
AND
DATEADD(hour, 10, DATEADD(day, DATEDIFF(day, 0, GETDATE()), 0))
If you use a variable in TSQL then store today's date in that
DATEADD(day, DATEDIFF(day, 0, GETDATE())
select ...
where dateColumn between
convert(varchar(10), getdate(), 120) + 'T08:00:00'
and convert(varchar(10), getdate(), 120) + 'T10:00:00'
I am tring to calculate the amount sum that will be 31 days past due or greater on the last day of the month. So far I have done this but I am not sure how do I apply the second condition for the last day of the month. Thanks for the tips
SELECT SUM(balance_amount) AS total_amount FROM MyTable
WHERE DATEDIFF(dd,date_due,date_paid) >= 31
Try something like this
Select Dateadd(d,-DATEPART(d,DateAdd(m,1,getdate())),DateAdd(m,1,getdate())) as [Last Day of Month]
You work out the last day of the CURRENT month by adding 1 month to today's date and then subtracting the number of days in this particular month. Try some edge cases like 28th Feb e.t.c.
Well clearly, on the last day of any month, the amounts that are 31 days overdue are the amounts for transactions dated 31 days prior to the end of the month, unless they have been paid.
Select Sum(t.Amount) - Sum(p.Amount)
From invoices t join payments p
On p.AccountNum = t.AccountNum
Where t.InvoiceDate < DateAdd(month, 1 + datediff(month, 0, getdate()), 0)-32
The expression in the last line, DateAdd(month, 1+datediff(month, 0, getdate()), 0) is the first of next month
I don't see (without access to your schema), how you can tell, just from the balance on the account, how much of the balance will be 31 days overdue at the end of the current month.
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.
This should not be this hard. I simply need the following:
SET #DueDate = CONVERT (DATETIME, '01/01/2010')
However, I need it pragmatically so that if it were March of 2010, the date given would be '01/01/2011'.
I know it's simple, but my brain isn't coming up with it. I'm sure it's with a DateAdd and getdate().
Number of year boundaries between now and year zero less one (31 dec 1899), add back on.
SELECT DATEADD(year, DATEDIFF(year, -1, GETDATE()), 0)
Let's try a date next year to get 2011. because 1 Jan 2010 is start of next year in 2009...
SELECT DATEADD(year, DATEDIFF(year, -1, '2010-03-21'), 0)
Based on the Database Journal article: How to Calculate Different SQL Server Dates:
First Day of the Next Year
I use the year interval (yy) to display the first day of the next year.
select DATEADD(yy, DATEDIFF(yy, -1, getdate()), 0)
Incidentally, with SQL 2012 you can do DATEFROMPARTS(YEAR(#date) + 1, 1, 1). In your case, DATEFROMPARTS(YEAR(GETDATE()) + 1, 1, 1)
Hat tip to https://stackoverflow.com/a/13873750/155892
Perhaps, create a table with first of the year dates, then pick the smallest that is larger than your date.
Perhaps simply put a string together, '01/01' + (MyYear + 1)?
You could add one to the current year, then concat with Jan 01, then convert back to date:
select CONVERT(datetime, CONVERT(VARCHAR(20), YEAR(GETDATE())+1) + '.01.01')
Using some parts of the examples above you could also do this. Now this assumes your acceptable date format matches M-d-yyyy.
DATEADD(year, 1,'1-1-'+convert(varchar,DATEPART(YYYY,GetDate())))
Note: You get the current date, get the year part, create a string that converts to a date, then add one to the year.