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...
Related
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))
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;
}
This query is selecting rows applied last 30 days:
SELECT `amount` FROM `mg_inputs` WHERE `amount`<0 AND `product`='144' AND DATE(firstedit) BETWEEN CURDATE() - INTERVAL 30 DAY AND CURDATE()
How about queries selecting rows applied last 30 days, but 1 month ago (between: today-30days and today-60days)? Same question goes for "2 months ago". Nothing is working for me at all (SQL is returning errors).
One important thing to note here is that not all months are 30 days, so instead of using INTERVAL DAY use INTERVAL MONTH.
Next, you don't need to use the subtraction sign for dates, you can use the DATE_SUB() function which will do what you need.
Last, keeping those things in mind, you can use the BETWEEN operator to check for rows within a date range. So, for example, if you want all rows from one month ago, try this:
SELECT *
FROM myTable
WHERE dateColumn BETWEEN DATE_SUB(CURDATE(), INTERVAL 2 MONTH) AND DATE_SUB(CURDATE(), INTERVAL 1 MONTH);
You should note that for the BETWEEN operator to work properly, the older date must appear first. Here is an SQL Fiddle example that demonstrates that.
I have a table "task_table" containing columns-
Task_id, Start_date, End_date
And I have one more "configuration" table which has the records that tell which days of the week are working days.
This table has two columns -
week_day, isHoliday
and this table contains seven records as week_days are the Monday,Tuesday.....Sunday , and each record has an entry as 1 or 0. If a day is a holiday in any organization then there will be 0 against that day. Like if an organisation has holidays on Wednesday and Friday every week then there will be 0 against Wednesday and Friday only.
Now I want to make a SQL query to get the Task_id, Start_date, End_date, and the count of total days consumed on each task. (These days are the days between task start_date and end_date excluding the holiday days as configured in "configuration" table.)
I don't have time to fully answer this question now, but what I would do is:
Get the date as at the start of the Start_date week, and the date as at the end of the End_date week (you can get this by date_adding an amount of days according to the day of the week.
Then you want to date diff them, divide by seven, multiply by two, and remove any that you would have added (e.g. if the start date was Thursday then you'll need to remove one from the result, as you will have counted one for the Wednesday immediately prior.
I'll write the code out tomorrow (it's late here - something like 14 hours from now or so.) if noone else has suggested a better answer.
Edit: Right, didn't properly read the question, but the tactic still applies with a little fiddling. Speaking of which, here is the fiddle of my solution.
It boils down to the following code:
set #holidaysPerWeek = (select sum(isHoliday) from configuration);
select
Task_id,
((dateDiff(
DATE_ADD(End_Date, INTERVAL 7 - DayOfWeek(End_Date) DAY),
DATE_ADD(Start_Date, INTERVAL -DayOfWeek(Start_Date) + 1 Day)) + 1) / 7)
* #holidaysPerWeek
- (select sum(isHoliday) from configuration where week_day > DayOfWeek(End_Date))
- (select sum(isHoliday) from configuration where week_day < DayOfWeek(Start_Date)),
DayOfWeek(End_Date)
from task_table
This does exactly what I was saying before, but with a variable number of "weekends" spread throughout the week, by first selecting the number of holidays for if the full weeks were covered, then removing holidays that were before or after the start and end dates respectively.
I want to pick and SUM values since last wednesday until NOW() in mysql. How can I do that?
Sorry for incomplete question, by the last Wednesday I did not mean to hard-code the date, rather I want my program to run that query, so it cannot hard-code--- Needs a flexible solution. Please help...
select date_sub(now(), interval dayofweek(date_sub(now(), interval 4 day)) day);
This works on any day of the week and always returns the Wednesday which has most recently passed. On a Wednesday itself, it returns the previous Wednesday. The next day, it returns yesterday
Genesis is right (He's very right, use his suggestion), but as an intellectual exercise: This is the best pure MySQL I could think of:
SELECT * FROM TABLE
WHERE
DATE_COLUMN > DATE_SUB( NOW(), INTERVAL DAYOFWEEK(NOW()) + 3 DAY);
NOW - DAYOFWEEK => this past Saturday. Weds. is three days before that.
SELECT SUM(value) FROM table WHERE date > '2011-07-20'
You should calculate your date from your programming language (fastest solution)