I am trying to create SQL query that calculates the number of hours between two dates (2015-01-01 12:12:12). The complexity of this query is on sum up hours only between Monday to Friday from 8am to 6pm.
I need it to calculate how long it took for a issue logged in our Mantis BT system to be resolved. Our clients can log issues outside our working hours, but I only want to calculate hours based on our working hours.
We calculate the difference between the date/time when the issue was logged (submitted_date) to when the issue was resolved (maximum updated_date and "resolved" status). The difficulty is that an issue can be resolved, and then reopened in the future. By using the maximum updated_date, my script is including the days that the issue was in "resolved" status, which is not correct. It should only include days while issue is open.
SELECT
proj.name,
bugs.id,
summary,
users2.username AS Assigned_to,
CASE bugs.status
WHEN '80' THEN 'Resolved'
WHEN '90' THEN 'Closed'
END AS Status,
bugs.date_submitted AS date_submitted,
MAX(date_modified) AS last_date_modified
FROM
mantis_bug_table bugs
LEFT JOIN mantis_bugnote_table notes ON notes.bug_id = bugs.id
INNER JOIN mantis_bug_history_table hist ON bugs.id = hist.bug_id
LEFT JOIN mantis_user_table users2 ON users2.id = bugs.handler_id
INNER JOIN mantis_project_table proj ON proj.id = bugs.project_id
WHERE
bugs.project_id = 102
AND hist.field_name = 'status'
AND bugs.status IN (80,90)
AND date_modified >= '2015-01-01'
GROUP BY
summary;
This tutorial is written for SQL, but can be replicated easily in MySQL.
You just need to define your working hours, then reference these to calculate the time.
Related
Frontend dev here trying to get a query working.
A bit of context, we have a site where users can keep track of time and our goal is to get them to 1000 hours of time tracked.
For this we have:
a pretty default users table, with a column track_outdoors (0 or 1, since they can enable or disable it) and a meta column (json field)
A timers table, where each row has a total_time column
What I want to do is select all users who:
Have tracking enabled (track_outdoors = 1),
Do not have MORE than 1000 hours total_time tracked,
Have not received the reminder email (check if meta column has 'ac_outdoors_outdoors_reminder_sent_at')
Where the last time they tracked time was more than 2 weeks ago
I've got the basic part done, which is retrieving the users who have enabled tracking, together with their total time tracked:
SELECT
u.id,
u.firstname,
u.track_outdoors,
SUM(t.total_time) AS total
FROM
users AS u
LEFT JOIN timers AS t ON u.id = t.user_id
WHERE
u.track_outdoors = 1
AND JSON_EXTRACT(u.meta, '$.ac_outdoors_outdoors_reminder_sent_at') IS NULL
GROUP BY
u.id
Now the two parts I'm having trouble with is using the sum to check if the total_time is smaller than 1000 and checking if the last time tracking was more than two weeks ago.
Apparently I cant use the SUM inside of the WHERE statement.
I tried searching on how to do a where last relationship is x time ago, but all I find is how to query records x days ago. (It needs to be the latest record x days ago, if that makes sense).
I think for the SUM in the WHERE statement I might need to use a subquery, but I'm not sure if that's true or how I'm supposed to do that. For the 2 weeks ago check, I understand how to check where the date is two weeks ago but not how to check that for the latest record for the user.
Any help would be much appreciated!
Thanks to the comment/answer provided by #Akina I was able to finish my query.
The result is:
SELECT
u.id,
u.firstname,
u.track_outdoors,
SUM(t.total_time) AS total
FROM
users AS u
LEFT JOIN timers AS t ON u.id = t.user_id
WHERE
u.track_outdoors = 1
AND JSON_EXTRACT(u.meta, '$.ac_outdoors_outdoors_reminder_sent_at') IS NULL
GROUP BY
u.id
HAVING total < 1000 AND MAX( t.created_at ) < CURRENT_DATE - INTERVAL 2 WEEK
So I needed to use HAVING for checking the total and MAX to check for the date of the tracker to be more than two weeks ago.
I have a query that brings back dates of inbound and outbound payments, and for each outbound payment i want to calculate the number of days since the previous inbound payment.
E.g.
SELECT
ps.clientid AS 'clientid',
psi.id AS 'scheduleid',
case when psi.status IN (4,5,6) then 'IB' when psi.status = 9 then 'OB' END AS 'type',
case when psi.status IN (4,5,6) then FROM_UNIXTIME(psit.date_cleared_on) when psi.status = 9 then FROM_UNIXTIME(psi.due_date) END AS 'date'
FROM payment_schedule_inbound psi
LEFT JOIN payment_schedule_inbound_transaction psit ON psit.payment_schedule_inbound_id = psi.id
INNER JOIN payment_schedule ps ON ps.id = psi.payment_schedule_id
WHERE psi.`status` IN (4,5,6,9)
AND ps.clientid IN (913244,913174) /*example id's, will usually run on multiple at same time or likely the full book*/
ORDER BY ps.clientid,(case when psi.status = 9 then psi.due_date else psit.date_cleared_on END)
(my CRM system stores dates as unixtime for some reason - not my fault, i didn't build the thing!)
What i want to do is, for each 'OB' event, display the datediff between that date and the previous 'IB' event for that clientid. In an ideal world i'd then like to have it only show the number of working days (excluding weekends), but that's whole other can of worms i can get to later!
I know the theory behind it would be to join the query back in on itself and get the max(date) of an IB event where the date is less than the date of the 'OB' event, but i'm just a layman and it's all got a bit much for me!
Any advice would be appreciated.
Thanks,
Ben.
I want to write a query to display jobs that are not yet expired. I also want to show the jobs that are expiring today.
SELECT jd.`job_title`,jd.`date_expiry`,jc.`category_title`
FROM `job_details` AS jd
JOIN `job_category` AS jc
ON jc.`category_id`=jd.`category_id`
WHERE jd.`company_id`=2
AND jd.`date_expiry` >= NOW()
ORDER BY jd.`date_expiry` ASC
The query works fine for jobs that are expired yesterday or before, but it does not show jobs that are expiring today. Jobs that are expiring today are supposed to be shown to users. Please help.
I think the problem with your query is that NOW() returns a timestamp at this exact moment in time, which could be in the middle of the day, the beginning, or the end. If NOW() were in the middle of the day, then anything expiring before that point would be excluded from your query. One workaround would be to compare to the current date at midnight.
You can use TIMESTAMP(CURRENT_DATE) to achieve this, and read here for a very helpful DBA Stack Exchange question.
SELECT
jd.job_title,
jd.date_expiry,
jc.category_title
FROM job_details AS jd
INNER JOIN job_category AS jc
ON jc.category_id = jd.category_id
WHERE jd.company_id = 2 AND
jd.date_expiry >= TIMESTAMP(CURRENT_DATE) -- compare to today at midnight
ORDER BY jd.date_expiry
I'm trying to pull the sum time worked for each user in a certain group over the next 30 days. I am not great at MySQL, so a lot of this may be wrong. This is from a JIRA database.
SELECT DISTINCT cu.display_name AS 'Associate', sum(wl.timeworked/3600) AS '30 Days'
FROM worklog AS wl, cwd_user AS cu
INNER JOIN cwd_membership AS cm
ON cu.directory_id=cm.directory_id
AND cu.lower_user_name=cm.lower_child_name
AND cm.membership_type='GROUP_USER'
INNER JOIN worklog
ON worklog.AUTHOR = cu.user_name
WHERE cm.lower_parent_name='atl_servicedesk_it_agents' AND wl.STARTDATE BETWEEN NOW() AND DATE_ADD(NOW(), INTERVAL 30 DAY)
ORDER BY cu.last_name;
Right now it just displays the first users name with a sum total of everything in the time worked for everyone. That is obviously not what I want... If I remove the sum from timeworked it shows about half of the users from that group, but each user has a value of 16 hours for timeworked, which is incorrect. Only one user has any value for the next 30 days and it is for 16 hours, so for some reason it is duplicating this information.
Any ideas?
Got it working by taking out the INNER JOINs.
SELECT cwd_user.display_name AS 'Associate', sum(worklog.timeworked/3600) AS '30 Days'
FROM worklog, cwd_user,cwd_membership
WHERE worklog.AUTHOR = cwd_user.user_name
and cwd_user.directory_id = cwd_membership.directory_id
and cwd_user.lower_user_name = cwd_membership.lower_child_name
and cwd_membership.membership_type = 'GROUP_USER'
and cwd_membership.lower_parent_name = 'atl_servicedesk_it_agents'
and worklog.STARTDATE BETWEEN NOW() AND DATE_ADD(NOW(), INTERVAL 60 DAY)
GROUP BY cwd_user. display_name
ORDER BY cwd_user.last_name;
I am creating a pipeline report so we can count opportunities that have been added each week.
My query is:
SELECT
sum(IF(o.date_entered > date_sub(now(), INTERVAL 1 WEEK), 1,0))
Pretty simple and works. The problem is, sales now also wants to count any opportunity as new that has been moved out of a loss status. So, I left-joined to an audit table to include this use case. But now, it counts every instance of the audit table for a given account where the field = sales_stage and the before_value is a loss status. So, and not that this would happen that often if ever, but if an opportunity moves from loss to lead, back to loss, and back to lead, it will count it as 2 new opportunities. I just want to get the latest instance of field=sales_stage and before_value is a loss status, and count that one time.
I want something like a sub-query in the left join, and I keep trying to use MAX, but nothing's working. Here's part of my join:
INNER JOIN opportunities o ON ao.opportunity_id=o.id
LEFT JOIN opportunities_audit oa ON o.id=oa.parent_id
AND after_value_string = 'Loss'
AND date_created > date_sub(now(), INTERVAL 1 WEEK)
Does anybody know the solution to this type of problem? Thank you in advance for any advice!