QUESTION
Is it possible the find the number of weeks in the current month using a MySQL query?
If you answer the above question, then you have answered my question. However, I have been downvoted before for not including context, so....
BACKGROUND (Warning: It Will Confuse You)
I advise not reading any further
Because of a MySQL parser we have written in an application, my hands are tied with the way in which I must approach writing queries.
Here's the scenario:
I need to average out the number of hours worked per week over the course of a month by an employee; however, I must approach this by generating a column returned by the query that can then be summed to give me the average (yes, that is a mouth full).
Here is what I mean (and one attempt):
SELECT ets.*, (ets.hours/4) AS AVG_HOURS
FROM employee_timesheet AS ets
WHERE ets.date_worked >= (NOW() - INTERVAL 1 MONTH)
Yes, the WHERE clause is not accurate, that will have to change, too (but that is the next step).
The application then SUMS(avg_hours). Consider that each ets record contains the hours worked per day, by dividing the (hours worked each day) / by the (floating representation of the number of weeks in the month), I should then get the average worked per week over the course of the month by summing the result of the division.
To represent the logic in pseudo-code:
SUM(days_hours/number_of_weeks)
You can use DATEDIFF function
SELECT DATEDIFF('2014-10-30','2014-12-29') AS DiffDate
it should return the days between two date
https://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html#function_datediff
To answer the question, yes you can find the number of weeks from a month by using SQL's
datepart(week, date).
If you need the current month's number of weeks you can do
Datepart(week, getdate())
Here's more information for DATEPART
To get the first day of the month you can use
DATEADD(month, DATEDIFF(month, 0, #mydate), 0)
Alright, I got it. If I want to get the current number of weeks elapsed in the current month, I can:
DAYOFMONTH(CURRENTDATE()) / 7
Related
I know this question may seem like a simple one and might have been asked before but what makes this tricky is how do I work out the total days for a payroll. Now my company's drivers work on how many days they are clocked onto a truck. I need to calculate the total amount of days they have been clocked in per month.
The payroll dates are the 25th of the previous month and the 26th of the current month. If a driver is clocked in before the 26th of the payroll month the amount of days still need to be calculated up until the 26th. Similarly if the driver was clocked in before the 25th and only clocks out during the payroll month only the days between the 25th and the clocked out date needs to be calculated.
I have a php solution to this but it created so many over heads and is not optimized at all, it also creates loading problems and the way the calculations are done is based of the amount clock outs and manually adding or subtracting days according to certain conditions. This is not a a very good way of calculating the amount of clocked in days per driver as you can see so I am trying to make a query that will handle the calculation of the days for the payroll.
the problem I have with this current query is that it seems not able to see that the date 2022-04-06 20:42 is smaller than 2022-04-25 07:59
provided below is the query and the data it's returning.... Just excuse the query it does seem a bit hard to follow as I still need learn how to create MySQL variables so there's a lot of repetition. (The STR_TO_DATE() is becasue the dates are being saved as type strings in the data base)
MySQL query:
SELECT
IF(STR_TO_DATE(OPENING_DATE, '%Y-%m-%d %H:%i') < DATE_FORMAT(CURRENT_DATE() - INTERVAL 1 MONTH, '%Y-%m-26 00:01'),
DATE_FORMAT(CURRENT_DATE() - INTERVAL 1 MONTH, '%Y-%m-26 00:01'),OPENING_DATE) AS OPENING_DATE,
IF(STR_TO_DATE(CLOSING_DATE, '%Y-%m-%d %H:%i') = '',
DATE_FORMAT(CURRENT_DATE(), '%Y-%m-25 23:59'), CLOSING_DATE) AS CLOSING_DATE,
TIME_TO_SEC(TIMESTAMPDIFF( MINUTE,
IF(STR_TO_DATE(OPENING_DATE, '%Y-%m-%d %H:%i') = '' ,
DATE_FORMAT(CURRENT_DATE() - INTERVAL 1 MONTH, '%Y-%m-26 00:01'),OPENING_DATE),
IF(STR_TO_DATE(CLOSING_DATE, '%Y-%m-%d %H:%i') < DATE_FORMAT(CURRENT_DATE(), '%Y-%m-25 23:59'),
DATE_FORMAT(CURRENT_DATE(), '%Y-%m-25 23:59'), CLOSING_DATE)
))/3600 AS TIME_DIFF_01
FROM HANDOVERS
WHERE (DRIVER_ID = '8308215990085');
Returned Data:
For reference this is the current data saved in the data base. Here you can compare the saved clocked in and out data to the data I'm trying to pull. I honestly don't know why the second batch of data has different days to the first.
How about this...
When you insert a row, check to see if it spans the month boundary (morning of the 26th). If it does, split it into two (or more) records.
Add an extra column that says which month the row belongs to.
With those, the Select becomes much simpler.
Given a table with two dates and a date interval (i.e. 6 WEEKS), how can I count how many times this interval fits in this date interval?
In my PHP script I'm using a simple for loop, but I'd like to add this in a MySQL query.
A simple calculation would be to count the number of days between the dates and then assume a month has 30 days and a year has 365 days, but that's not always true.
How can I calculate with datediff and a date interval string?
When I understood you correctly, you need the timestampdiff() function.
The first parameter is the unit of the interval. The result is how many units are between the two dates.
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))
I am running MYSQL version 4.0.16. My hosting provider manages the server and therefore I cannot upgrade to a later version.
I have been given a task of building a help desk report. It needs to show the total number of calls over an 8 day period per day , the total number of calls closed on the same day and it then needs to show the average number of calls for each of these days over an 30 day period.
For formatting purposes I have had to left join a list of dates. This is purely so my report will not have any missing dates.
I am struggling to figure out how I can calculate the average number of calls per date over a 30 days period. Can anyone help me do this? The average should be calculated per day, so the function needs to count all of the calls over the last 30 days prior to each date and then divide this by 30 to calculate the average.
SELECT COUNT(call_id)/30
FROM call_table
WHERE call_date BETWEEN curdate() and adddate(curdate() interval -30 day)
Not tested. I normally use SQL server so the MySQL syntax may be slightly off, but if I am understanding you correctly then it would be similar to this.
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...