I am creating a report where I have to show last 7 days data and previous 7 days data. But I can fetch last 7 days data but for previous 7 days I don't know how to write the sql!
Suppose today is 14th March. I am fetching data from database for last 7 days which is 8th March to 14th March is,
WHERE my_date >= DATE_ADD(NOW(), INTERVAL -7 DAY)
But how to write the sql for previous 7 days? Which is 1st March to 7th March.
I have tried this,
WHERE my_date BETWEEN DATE_SUB(NOW(),INTERVAL 7 DAY) and NOW()
I don't think it's working! How am I going to get data for 1st March to 7th March and skip 8th March to 14th March?
Have you try this :
WHERE my_date BETWEEN DATE_SUB(NOW(),INTERVAL 14 DAY) and DATE_SUB(NOW(),INTERVAL 7 DAY)
How do I get the nth previous working date in MySQL?
Suppose the function signature is
nth_previous_working_date (d DATE, n INT)
For 10th September, 2015, the function should return 3rd September, 2015
You can use the date_sub function.
SELECT DATE_SUB('2015-09-10', INTERVAL 7 DAY);
or simply use the minus operator
SELECT '2015-09-10' - INTERVAL 7 DAY
See the working example.
Getting the previous non-weekend working day can be done with a case.
select case dayofweek(curdate() - interval 1 day) -- yesterday
when 1 then curdate() - interval 3 day -- when sunday, go 2 more days before
when 7 then curdate() - interval 2 day -- when saturday, go 1 more days before
else curdate() - interval 1 day -- yesterday
end
Ex. If I enter today's date 2014-06-23 it should show me previous year's last Sunday date i.e. 2013-12-29. Should not use any procedure / sub-queries, it should be only a single query. Im using MySQL. Kindly help.
Try something like this:
select (date(now()) - interval dayofweek(now()) - 1 day) - interval (weekofyear(now()) - 1) * 7 day
This will return last year Sunday of Current Month
SELECT DATE_SUB(DATE(NOW()), INTERVAL DAYOFWEEK(NOW())-1 year) last_sun
Fiddle Demo
This will return Last year last sunday
SELECT (DATE_SUB(DATE(NOW()), INTERVAL DAYOFWEEK(NOW())-1 day))- INTERVAL (WEEKOFYEAR(NOW()) - 1) * 7 DAY AS Sunday
Fiddle Demo
I have a select statement of which needs to base its WHERE on a timestamp but for all dates within that week beginning monday.
The MySQL
SELECT DISTINCT(unique_reference) AS unique_reference, date(datetime) AS datetime
FROM sales_tickets
WHERE Date(datetime)='$datetime'
This is based on the fact that $datetime can be any date but the select statement needs to get all records from that week, example: if its the Monday 12th May 2014, it will fetch all results from that week, instead of the one day.
Currently, its fetching only one day of results.
I have no idea how to rectify this issue. Any advise would be awesome thanks.
You can compare using the WEEK function :
WHERE WEEK(DATE(datetime)) = WEEK('$datetime')
If you have multiples years for entries, you can use instead the YEARWEEK function.
Edit for first day of week:
WEEK and YEARWEEK functions have both a second optional argument which tells when a week start. Try to consider mode 1 or 5.
Mode First day of week Range Week 1 is the first week …
0 Sunday 0-53 with a Sunday in this year
1 Monday 0-53 with 4 or more days this year
2 Sunday 1-53 with a Sunday in this year
3 Monday 1-53 with 4 or more days this year
4 Sunday 0-53 with 4 or more days this year
5 Monday 0-53 with a Monday in this year
6 Sunday 1-53 with 4 or more days this year
7 Monday 1-53 with a Monday in this year
A sargable solution would explicitly calculate the start and end points of your desired range:
WHERE datetime >= DATE('$datetime') + INTERVAL 0 - WEEKDAY('$datetime') DAY
AND datetime < DATE('$datetime') + INTERVAL 7 - WEEKDAY('$datetime') DAY
The easiest method might be to have your WHERE statement check against a range of values, which you can calculate beforehand.
I'll assume you're using php.
So your SQL statement will be:
SELECT DISTINCT(unique_reference) AS unique_reference, date(datetime) AS datetime
FROM sales_tickets
WHERE (Date(datetime) > '$startDate')
AND (Date(datetime) < '$endDate');
You'll first have to figure out what $startDate and $endDate are:
$endDate = strtotime('Monday', time()); // might need to adjust this depending on when your week starts
$startDate = $endDate - 7*24*60*60; //one week before.
Be careful with converting times between unix timestamps and datetimes used in SQL, but you get the idea.
Try WEEK():
WHERE WEEK(datetime)=WEEK('$datetime')
Read more: WEEK()
I am trying to calculate last years starting day of the "current week NOW()" and the ending day of that week. Along with this I am needing an offset as sometimes the Starting day of the week may not be Sunday or Monday, but even possibly a Thursday.
If a week starts on a Tuesday for instance it will end on a Monday. Given this if the current day is Thursday I need to be able to calculate the Tuesday and Monday.
I understand how to get last years current day.
SELECT DATE_SUB(NOW(), INTERVAL 1 YEAR);
But with the offset requirement here I am having issues calculating the starting day of that week and ending day of that week. Which needs to be in a "date format."
* Working to clarify this more... My example was off...
***Edit
For the sake of argument (and example), let's say that today is Jan 23, 2012. My task is to accept that date and return the start and end dates for that week of the previous year.
My assumptions are:
1) a week is defined as having a thursday (ie 2011 week 1 is 1/2 - 1/8)
2) start of week is Sunday
According to the week numbering scheme as I understand it with the above assumptions, week 1 is the first week with a Thursday. That means, Jan 23 falls within week 4 in 2012. This is confirmed with WEEK('2012-01-04') = 4. My target thus is to select the start and end dates of week 4 of the previous year. In 2011, the results would be Jan 23 - Jan 29.
Complicating this further is then to adjust the start of the week (modify assumption 2). Continue to use WK4... 2011, Jan 23 - Jan 29, Sun - Sat, If I say the start of the week is Monday, then I would adjusting the dates by one... giving Jan 24 - Jan 30. Tues adjusts by 2... Jan 25 - Jan 31, etc.
The approach is two steps:
1) calculate the start and end of the true year week
2) slide it into the "future" by whatever the start day would be
While the sliding into the future may or may not be correct, it would at least yield consistent results based on the conventional understanding of what "week 4" means.
Unfortunately PHP is not necessarily an option here. We need this to be ran inside of a SELECT START_WEEK, END_WEEK;
Any advice or help towards solving this query would be much helpful.
Thanks
Well, ISO 8601 assumes:
a week is defined as having a Thu
the start of a week is Mon
Jan 23 falls within week 4 of 2012 which you can confirm with
SELECT WEEK('2012-01-23', 3) = 4;
Week 4 of 2012 is Jan 23 to Jan 29 which you can confirm with the calendar at whatweekisit.com. As a query, you can calculate with:
SELECT
WEEK('2012-01-23', 3) AS weekNumber,
DATE_SUB('2012-01-23', INTERVAL DAYOFWEEK('2012-01-23') - 2 DAY) AS startOfWeek,
DATE_ADD('2012-01-23', INTERVAL 8 - DAYOFWEEK('2012-01-23') DAY) as endOfWeek;
Week 4 of 2011 is Jan 24 to Jan 30 (also confirmable by calendar). It is true that same date may not fall within the current week number and last year's week, but I don't suspect they would be wildly different.
SELECT
IF (WEEK('2012-01-23', 3) = WEEK(DATE_SUB('2012-01-23', INTERVAL 1 YEAR), 3),
DATE_SUB(DATE_SUB('2012-01-23', INTERVAL 1 YEAR), INTERVAL DAYOFWEEK(DATE_SUB('2012-01-23', INTERVAL 1 YEAR)) - 2 DAY),
DATE_SUB(DATE_SUB(DATE_ADD('2012-01-23', INTERVAL 6 DAY), INTERVAL 1 YEAR), INTERVAL DAYOFWEEK(DATE_SUB(DATE_ADD('2012-01-23', INTERVAL 6 DAY), INTERVAL 1 YEAR)) - 2 DAY)) AS datetimeStart;
Notice that I'm always representing the calculations verbatim in several places (e.g. DATE_SUB('2012-01-23', INTERVAL 1 YEAR) of Jan 32 2011); if you're doing this within a stored procedure or UDF you can probably use variables to make it more concise/readable/maintainable.
Now that the start and end of the target year week has been identified, you can simply apply your offset. Given $weekDayStart is 0 - 6 (Sun - Sat):
SELECT
DATE_ADD(
IF (WEEK('2012-01-23', 3) = WEEK(DATE_SUB('2012-01-23', INTERVAL 1 YEAR), 3),
DATE_SUB(DATE_SUB('2012-01-23', INTERVAL 1 YEAR), INTERVAL DAYOFWEEK(DATE_SUB('2012-01-23', INTERVAL 1 YEAR)) - 2 DAY),
DATE_SUB(DATE_SUB(DATE_ADD('2012-01-23', INTERVAL 6 DAY), INTERVAL 1 YEAR), INTERVAL DAYOFWEEK(DATE_SUB(DATE_ADD('2012-01-23', INTERVAL 6 DAY), INTERVAL 1 YEAR)) - 2 DAY)),
INTERVAL $weekDayStart - 1 DAY) AS datetimeStart,
DATE_ADD(
IF (WEEK('2012-01-23', 3) = WEEK(DATE_SUB('2012-01-23', INTERVAL 1 YEAR), 3),
DATE_SUB(DATE_SUB('2012-01-23', INTERVAL 1 YEAR), INTERVAL DAYOFWEEK(DATE_SUB('2012-01-23', INTERVAL 1 YEAR)) - 2 DAY),
DATE_SUB(DATE_SUB(DATE_ADD('2012-01-23', INTERVAL 6 DAY), INTERVAL 1 YEAR), INTERVAL DAYOFWEEK(DATE_SUB(DATE_ADD('2012-01-23', INTERVAL 6 DAY), INTERVAL 1 YEAR)) - 2 DAY)),
INTERVAL $weekDayStart + 5 DAY) AS datetimeEnd;
So, working it through with the input of 2012-01-23 and start day of Thurs would yield:
Jan 23 2012 = week 4
week 4 of 2011 = 1/24-1/30
Offset Thu - Mon (4 - 1) is +3 which moves window to Jan 27 - Feb 2 2011
Found it... Had to read up on the issue a little more.
This ended up being 7 different queries.
My Base Query:
Sunday Start Day of Week
SELECT
DATE_SUB(
DATE_ADD(
STR_TO_DATE( CONCAT( YEAR('2012-01-04')-1, '-01-01' ), '%Y-%m-%d'), #Get last year starting date.
INTERVAL WEEK('2012-01-04') WEEK),
INTERVAL 6 DAY) START_DAY_OF_WEEK,
DATE_ADD(
STR_TO_DATE( CONCAT( YEAR('2012-01-04')-1, '-01-01' ), '%Y-%m-%d'),
INTERVAL WEEK('2012-01-04') WEEK) END_DAY_OF_WEEK;
This gets me Week 1 of 2011. Starting of that week is 1/2 and ending on 1/8.
Now if my week starts on a different day I add in an offset...
Tuesday Start Day of Week
SELECT
DATE_SUB(
DATE_ADD(
STR_TO_DATE( CONCAT( YEAR('2012-01-04')-1, '-01-01' ), '%Y-%m-%d'), #Get last year starting date.
INTERVAL WEEK('2012-01-04') WEEK),
INTERVAL 4 DAY) START_DAY_OF_WEEK,
DATE_ADD(
DATE_ADD(
STR_TO_DATE( CONCAT( YEAR('2012-01-04')-1, '-01-01' ), '%Y-%m-%d'), #Get last year starting date.
INTERVAL WEEK('2012-01-04') WEEK),
INTERVAL 2 DAY) END_DAY_OF_WEEK;
This will give me 1/4 start day of week and ending on 1/10.
To get the other days of the week is relatively simple:
Sunday (First Query...)
Monday -5 start day +1 end day.
Tuesday -4 start day +2 end day.
Wednesday -3 start day +3 end day.
Thursday -2 start day -4 end day.
Friday -1 start day -5 end day.
Saturday -0 start day -6 end day.
It is 7 separate queries but does enable me to do what I was intending to do.