MySQL Date For Monthly Reporting - mysql

I need some help with running a query at month end. Each 1st working day of a month may differ, and therefore I may only be at work on the 3rd of a given month.
I am trying to figure out what my WHERE statement would look like to select data for the current month, unless it is:
1st of a month, then it will need to select everything from the previous month
1st working day of a month, which could be the 3rd. It will then also need to select the previous month's data.
These are two scenarios I am currently playing with, and don't have data to test it with as yet.
I have thought about doing
WHERE
MONTH(action_date) = MONTH(DATE_SUB(CURDATE(),INTERVAL 1 DAY))
But this then also returns data from 2016.
I have also thought of doing
WHERE
action_date = DATE_SUB(CURDATE(),INTERVAL 1 DAY)
But this would not work if today was say Monday the 3rd.
I would appreciate any answers that would give me the best way of doing this

You could simply subtract a few more days or even a month from the date, as all you will actually get from the subtraction is a month anyway
MONTH(DATE_SUB(CURDATE(),INTERVAL 5 DAY))
OR
MONTH(DATE_SUB(CURDATE(),INTERVAL 1 MONTH))

Related

Date Intervals Doesn't work

I am trying to get data by week, month and year.
I store date YYYY-MM-DD HH:MM:SS.
What I am doing is below;
Fetch one week old data;
query + AND WEEK(date) = WEEK(CURDATE())
Fetch a month old data;
query + AND MONTH(date) = MONTH(CURDATE())
The thing is I couldnt be able to get the data correct. For instance when I want to get week old data, I am gettin a year old one too.
Is there any other query that I could use? I have tried DATE(NOW()) - INTERVAL 30 DAY. It works but very slow.
Thanks!
I believe that the problem is that the WEEK function returns the week of the year. So, Jan 1st 2017 might be week 1 (also might be week 53 of the previous year depending on the day of the week and how MySQL handles it). But then, Jan 1st of 2016 is also week 1 - just for a different year.
Trying changing it to:
query + AND WEEK(date) = WEEK(CURDATE()) AND YEAR(date) = YEAR(CURDATE())
Also, if you're storing this as a string then definitely change it to a DATETIME
WHERE ...
AND date >= CURDATE() - INTERVAL 7 DAY
AND date < CURDATE()
Gives you the 7 days ending with yesterday. Use other techniques to get a particular month or week.
This technique is also much faster for large tables with a suitable index. Hiding date inside a function, such as WEEK() prevents the use of an index.

Rewritten mySQL Statement

SELECT DATE(STR_TO_DATE(CONCAT(CONCAT(YEAR('$uDate1'), week), ' Monday'), '%X%V %W') +
INTERVAL (7 - DAYOFWEEK(STR_TO_DATE(CONCAT(CONCAT(YEAR('$uDate1'), week), ' Monday'),
'%X%V %W'))) DAY)
as week_end_date
What this statement does is take the date I give it ($uDate1) and give me the week end date (Saturday) of that week. This works well and I am happy with it, kinda.
I was wondering if there were some things I missed that would either make this more efficient or even if I missed some shortcuts to this.
Any suggestions for me?
week >= WEEK('$uDate1') AND week <= WEEK('$uDate2')
This is in my WHERE clause. So basically if I use this...
DATE('$uDate1', INTERVAL 7 - DAYOFWEEK('$uDate1') DAY)
...then it returns the same day for all records. I need it to be able to go over a span of a few weeks.
I have a column in my database named 'week'. It simply stores an INT that corresponds to the week of the year. (ex. 21 for this week)
I then have two date picker boxes. The output gets the week end date based of each week that is BETWEEN and INCLUDES the days chosen.
5/10/2016 & 5/26/2016 outputs 5/14/2016, 5/21/2016, 5/28/2016
What gets exported to CSV file looks something like this..
WEEK END, LAST NAME, FIRST NAME, ...
5/10/2016, Smith, John, ...
5/26/2016, Jones, James, ...
It outputs anyone who had hours during the week, with the week end date.
SIDE NOTE: I do appreciate the comments and help. I don't want anyone to stress over this though! Just curious if better way. :)
I am not sure why your current SQL is so complicated.
You say it is just to take a date and give me the week end date (Saturday) of that week .
How you are doing this at the moment is:-
Yours is taking the year
Adding the week of the year (I assume - should be WEEK('$uDate1') I think)
Adding on the day as a string (so for example for today it would be 2016 21 Monday )
Changing that string back to a date a datetime value
Converting that datetime value back to a date.
Then taking the year again
Adding the week of the year again
Getting the day of the week of the resulting string. As you have concatenated Monday on to the date then the day of the week will always be 2.
Taking that resulting day of the week and subtracting it from 7. As the day of the week will always be 2 this will always result in 5
Adding on the day as a string (so for example for today it would be 2016 21 Monday ).
This value is then added on to the previously calculated date, taking the Monday date and adding 5 days.
My suggestion was to just use:-
DATE_ADD($uDate1, INTERVAL 7 - DAYOFWEEK($uDate1) DAY)
which is far simpler, and appears to cover your requirements.
EDIT
Looking at your edit you want a list of all the Saturdays for weeks all or partially between 2 passed dates.
If so I think the following will do it and hopefully be more efficient as there is no need to translate dates to and from string. Note it relies on your week table to add to the date, hence only copes with date ranges of up to that many weeks.
SELECT DATE_ADD(DATE_ADD('$uDate1', INTERVAL 7 - DAYOFWEEK('$uDate1') DAY), INTERVAL `week` WEEK) AS aDate
FROM `week`
HAVING aDate BETWEEN '$uDate1' AND DATE_ADD('$uDate2', INTERVAL 7 - DAYOFWEEK('$uDate2') DAY)
ORDER BY aDate
As I mentioned in comment you should move this transformation from mysql query to php code.
I see no reason to do this calculation on mysql side.
http://ideone.com/48zLvF
$week_day = intval(date('w',$uDate1));
if ($week_day<6) {
$end_of_week = $uDate1+(86400*(6-$week_day));
} else {
$end_of_week = $uDate1;
}

Fetch mysql data of timstamp depending on time given

I have a column with timestamp, contain example value "2014-04-16 18:00:00","2014-04-17 18:00:00"....
Now, if I will call a page before "2014-04-17 12:00:00" I need this value-"2014-04-16 18:00:00"
And if I call my page after "2014-04-17 12:00:00" I need this value "2014-04-17 18:00:00".
I think my question is very complicated to understand, having complications in date & times, please check date & time properly.
I want to fetch this data from DB in mysql, The page I was saying is that where I'm going to add your mysql query.
Thanx in advance
Generalising what your asking for a bit the following will return dates from the previous day if it's before noon and dates from today if it's after noon:
SELECT date_column
FROM yourTable
WHERE DATE(DATE_SUB(NOW(), INTERVAL 12 HOUR)) = DATE(date_column);
Edit:
The WHERE clause First gets the current time (NOW()) and subtracts 12 hours. This wont affect the date unless the time is before 12. This means DATE_SUB(NOW(), INTERVAL 12 HOUR) gives us today if it's after noon and yesterday if it's before.
We then check if the date_column matches the date we've created (using the DATE function so that the time is ignored).
Adding some rows to the SELECT may help you see how these dates are built up.

Select dates within the last week, but not only last 7 days

I want to select all dates within the last week.
But not by simply counting the current date - 7, as all posts Ive come across suggest.
This is how I actually have it for the SUM now....
SELECT SUM(total) FROM payforms WHERE user_id = 1 GROUP BY WEEK(date)
This gives me a nice total...
But I want to retrieve all individual records within the last week.
So I can use a BETWEEN query....but how do I get it to look in the current week.
Example...
Tuesday I want it to only find values from Sun, Mon, Tue.
On wednesday, I want it to find Sun, Mon, Tue, Wed.
On Saturday it finds the whole previous week. etc
So to be more clear....
I dont want it to find last Monday, on a monday.
On Mondays it should only display Mondays, if you get what I mean.
Can I do this??
Thanks
select * from payforms where yearweek(date) = yearweek(now());
Although I think MySQL weeks start on Sunday
You can make use of the WEEKDAY date function, which returns the day index of the week.
If I understand your question correctly, you could use this query:
SELECT date, SUM(total)
FROM payforms
WHERE date >= CURDATE() - INTERVAL DAYOFWEEK(CURDATE())-1 DAY
GROUP BY date
Please see fiddle here.
This will SUM all totals for every day of the current week, starting on last Sunday. If you want it to start on last Monday you can use this:
WHERE date >= CURDATE() - INTERVAL WEEKDAY(CURDATE()) DAY

How do I select two weeks ago in MYSQL?

I have a report that is driven by a sql query that looks like this:
SELECT batch_log.userid,
batches.operation_id,
SUM(TIME_TO_SEC(ramses.batch_log.time_elapsed)),
SUM(ramses.tasks.estimated_nonrecurring + ramses.tasks.estimated_recurring),
DATE(start_time)
FROM batch_log
JOIN batches ON batch_log.batch_id=batches.id
JOIN ramses.tasks ON ramses.batch_log.batch_id=ramses.tasks.batch_id
JOIN protocase.tblusers on ramses.batch_log.userid = protocase.tblusers.userid
WHERE DATE(ramses.batch_log.start_time) > "2011-02-01"
AND ramses.batch_log.time_elapsed > "00:03:00"
AND DATE(ramses.batch_log.start_time) < now()
AND protocase.tblusers.active = 1
AND protocase.tblusers.userid NOT in ("ksnow","smanning", "dstapleton")
GROUP BY userid, batches.operation_id, date(start_time)
ORDER BY start_time, userid ASC
Since this is to be compared with the time from the current payperiod it causes an error.
Our pay periods start on a Sunday, the first pay period was 2011-02-01 and our last pay period started the 4th of this month. How do I put that into my where statement to strip the most recent pay period out of the query?
EDIT: So now I'm using date_sub(now(), INTERVAL 2 WEEK) but I really need a particular day of the week(SUNDAY) since it is wednesday it's chopping it off at wednesday.
You want to use DATE_SUB, and as an example.
Specifically:
select DATE_SUB(curdate(), INTERVAL 2 WEEK)
gets you two weeks ago. Insert the DATE_SUB ... part into your sql and you're good to go.
Edit per your comment:
Check out DAYOFWEEK:
and you can do something along the lines of:
DATE_SUB(DATE_SUB(curdate(), INTERVAL 2 WEEK), INTERVAL 2 + DAYOFWEEK(curdate()) DAY)
(I don't have a MySql instance to test it on .. but essentially subtract the number of days after Monday.)
Question isn't quite clear, especially after the edit - it isn't clear now is the "pay period" two weeks long or do you want just last two weeks back from last sunday? I assume that the period is two weeks... then you first need to know how many days the latest period (which you want to ignore, as it isn't over yet) has been going on. To get that number of days you can use expression like
DATEDIFF(today, FirstPeriod) % 14
where FirstPeriod is 2011-02-01. And now you strip that number of days from the current date in the query using date_sub(). The exact expression depends on how the period is defined but you should get the idea...