I have a table in a database with one column containing dates and another one containing scores. Basically, what I want to do is grab the best score in a given week.
Weeks can start on any given day (From Friday to Thursday, for instance), and that is defined by the user.
Here is what I have so far:
SELECT MAX(Series), DATE(DATE(Date, 'weekday 0'), '-7 days') dateStartOfWeek FROM SeriesScores
WHERE Season = '2010-2011'
AND dateStartOfWeek = '2010-08-29'
GROUP BY DateStartOfWeek
Where Series is the column containing the scores and Date is the (badly) named actual date.
The problem with this query is that it works for every day except for the day the week is supposed to be starting on.
For example: 2010-08-29 is a Sunday and in this example, I'm trying to find on which date the Sunday of the given week is. My function works for every day of that week except for 2010-08-29 (Sunday) since it tries to find the next day that is a Sunday (itself in this case). To compensate for that, I go back 7 days to get the correct Sunday, which creates the error for the already correct Sunday since this one doesn't need to go back 7 days or else it is one week off.
I figured I could solve this problem easily using Java, but I want to see how it should be done using SQL instead.
My solution (I don't even know if it can be done), would be to check if date and dateStartOfWeek are the same. If they are, don't substract 7 days from the date. If they're not, do as I did in my example. I don't know how to use conditions such as this one in SQL, though, and this is where I need help.
Thanks a lot in advance!
I think you need to use CASE operator - see http://sqlite.awardspace.info/syntax/sqlitepg09.htm
EDIT - try:
SELECT MAX(Series), CASE WHEN STRFTIME ( '%w', Date ) = 0 THEN DATE(Date, 'weekday 0') ELSE DATE(DATE(Date, 'weekday 0'), '-7 days') END AS dateStartOfWeek FROM SeriesScores
WHERE Season = '2010-2011'
AND dateStartOfWeek = '2010-08-29'
GROUP BY DateStartOfWeek
see http://www.sqlite.org/lang_datefunc.html
Related
I have a below query that I run to extract material movements from the last 7 days.
Purpose is to get the data for the last calender week for certain reports.
select
*
From
redshift
where
posting_date between CURRENT_DATE - 7 and CURRENT_DATE - 1
That means I need to run the query on every Monday to get the data for the former week.
Sometimes I am too busy on Monday or its vacation/bank holiday. In that case I would need to change the query or pull the data via SAP.
Question:
Is there a function for redshift that pulls out the data for the last calender week regardless when I run the query?
I already found following solution
SELECT id FROM table1
WHERE YEARWEEK(date) = YEARWEEK(NOW() - INTERVAL 1 WEEK)
But this doesnt seem to be working for redshift sql
Thanks a lot for your help.
Redshift offers a DATE_TRUNC('week', datestamp) function. Given any datestamp value, either a date or datetime, it gives back the date of the preceding Sunday.
So this might work for you. It filters rows from the Sunday before last, up until but not including, the last Sunday, and so gets a full week.
SELECT id
FROM table1
WHERE date >= DATE_TRUNC('week', NOW()) - INTERVAL 1 WEEK
AND date < DATE_TRUNC('week', NOW())
Pro tip: Every minute you spend learning your DBMS's date/time functions will save you an hour in programming.
I need to round up a month-date based on certain parameters. For example: If I have a parameter where if a day in a given month is between the 6th and the 4th of the next month, I need my query to return the next months date. Is there a way to round up the month given these parameters without hard coding case whens for every single month ever?
SELECT case when date_trunc('day',li.created_at between '2019-03-06 00:00:00' and '2019-04-06 00:00:00' then '2019-04-01' end)
FROM line_items li
If you want the beginning of the month, but offset by 4 days, you can use date_trunc() and subtract some number of days (or add some number of days). You seem to want something like this:
select dateadd(month, 1, date_trunc('month', li.created_at - interval '4 day'))
Another approach is to create a canonical "dates" table that precomputes the mapping from a given date to a new date using your rounding scheme. The mapping could be done outside of redshift in a script and the table loaded in (or within redshift using a user defined function).
I work for a company where everyday I modify a query by changing the date of the day before, because the report is always from the previous day.
I want to automate the date change. I have made a table with two columns, one with all dates from this year and another with bits where if 0 is a working day and 1 if is a holiday.
I have successfully automated a little bit by telling if the day before is a working day then subtract 1 from the date (This is what happens everyday). But the problem is, that if is Monday appears as Friday, because Saturday and Sunday are not billable. And let's also say, that if today is Thursday and Wednesday and Tuesday we're holidays, then the report will run on Monday. I will leave you a picture, that shows how the table is made with dates.
Remembering, that if there is no holidays in the middle of the week, always will be subtract one.
The way to do this sort of thing is close to what you have done, but just extend it further. Create a BusinessDate table that has every date, and then every rule you have implemented inside it. You can go so far as to include a column such as ReportDate which will return,for every date, what date the report should be run for.
Do this once, and it will work forever more. You may have to update for future holidays once a year, but better than once a day!
It will also allow you to update things specific for your business, like quarter dates, company holidays, etc.
If you want to know more on the subject, look up topics around creating a date dimension in a data warehouse. Its the same general issue you are facing.
Too complicated for a comment and it involves a lot of guessing.
So everyday, your process starts by first determining if "today" is a work day. So you would do something like:
if exists (select * from <calendar> where date = cast (getdate() as date) and IsWorkday = 1")
begin
<do stuff>
end;
The "do stuff" section would then run a report or your query (or something that isn't very clear) using the most recent work day prior to the current date. You find that date using something like:
declare #targetdate date;
set #targetdate = (select max(date) from <calendar>
where date < cast (getdate() as date)
and IsWorkday = 1);
if #targetdate is not null
<run your query using #targetdate>
That can be condensed into less code but it is easier to understand when the logic is written step-by-step.
I need a WHERE statement where the date of the record is the previous day. I have the below code which will do this
WHERE DOC_DATE = dateadd(day,datediff(day,1,GETDATE()),0)
However I need this statement to get Friday's record when the current day is Monday. I have the below code but it will not work for me. No errors come back on SQL although no records results come back either. I have the below code for this
WHERE DOC_DATE = DATEADD(day, CASE WHEN datepart(dw,(GETDATE())) IN (2) then -3 ELSE -1 END ,0)
Important to add that this needs to be in a WHERE clause. This is for a Docuware administrative view I am creating. I have no control on how to write the SELECT statement, I only have access to edit the WHERE clause:
Here's a slightly "magical" way to compute the value that doesn't depend on any particular server settings such as datefirst. It's probably not immediately obvious how it works:
WHERE DOC_DATE = dateadd(day,datediff(day,'20150316',getdate()),
CASE WHEN DATEPART(weekday,getdate()) = DATEPART(weekday,'20150330')
THEN '20150313'
ELSE '20150315' END)
In the first line, we're computing the number of days which have elapsed since some arbitrary date. I picked a day in March 2015 to use as my base date.
The second line asks what today's day of the week is and if it's the same as some arbitrary "Known good" Monday. Just taking one value and comparing it to 2 depends on what your DATEFIRST setting is so I prefer not to write that.
In the third line, we decide what to do if it's a monday - I give a date that is 3 days before my arbitrary date above. If it wasn't a monday, we pick the day before.
Adding it all together, when we add the days difference from the arbitrary date back to one of these two dates from lines 3 and 4, it has the effect of shifting the date backwards 1 or 3 days.
It's can be an odd structure to see if you're not familiar with it - but combining dateadd/datediff and exploiting relationships between an arbitrary date and other dates computed from it can be useful for performing all kinds of calculations. A similar structure can be used for computing e.g. the last day of the month 15 months ago using just dateadd/datediff, an arbitrary date and another date with the right offset from the first:
SELECT DATEADD(month,DATEDIFF(month,'20010101',GETDATE()),'19991031')
As I said in a comment though, usually doing this sort of thing is only a short step away from needing to properly model your organisation's business days, at which point you'd typically want to introduce a calendar table. At one row per day, 20 years worth of pre-calculated calendar (adjusted as necessary as the business changes) is still less than 10000 rows.
You can try this.
WHERE DOC_DATE = DATEADD(DAY, CASE WHEN datepart(dw, GETDATE()) = 2 THEN -3 ELSE -1 END, CAST(GETDATE() AS DATE))
Greetings all knowing Stack.
I am in a bit of a pickle, and I am hoping for some friendly assistance form the hive mind.
I need to write a query that returns the difference in days between a registration date (stored in a table column) and the first day of the last September.
For example; assuming the query was being run today (24-10-2016) for a record with a registration date of 14-07-2010, I would want the script to return the difference in days between 14-07-2010 and 01-09-2016
However had I run the same query before the end of last August, for example on 12-08-2016, I would want the script to return the difference in days between 14-07-2010 and 01-09-2015.
I'm fine with the process of calculating differences between dates, it's just the process of getting the query to return the 'first day of the last September' into the calculation that is tripping me up!
Any input provided would be much appreciated.
Thankyou =)
Try this approach:
add four months to the current date
truncate this date to the first of year
subtract four months again
Add_Months(Trunc(Add_Months(SYSDATE, 4), 'year'), -4)
Hope this might help.
WITH T AS (SELECT TO_DATE('14-07-2010','DD-MM-YYYY') REG_DATE,
SYSDATE EXEC_DATE
FROM DUAL)
SELECT CASE WHEN TO_CHAR(EXEC_DATE,'MM') >= 9
THEN ADD_MONTHS(TRUNC(EXEC_DATE,'YEAR'),8)
ELSE ADD_MONTHS(TRUNC(ADD_MONTHS(EXEC_DATE,-12),'YEAR'),8)
END
- REG_DATE AS DIFF
FROM T;