Question

Currently trying to find a way to do the following inside some form of loop (preferably without a performance hit on database).

I have 3 tables user_hours, user_calendar and hours_statistics. I need to first do:

SELECT user_calendar.date_start,
       user_calendar.opportunity_id,
       user_hours.user_id,
       user_hours.agreed_hours,
       user_hours.completed_hours,
       user_hours.hours_committed
FROM   user_calendar
       JOIN user_hours
         ON user_calendar.user_calendar_id = user_hours.user_calendar_id
WHERE  user_calendar.date_start = CURRENT_DATE()
       AND user_hours.completed_hours IS NULL
       AND user_hours.hours_committed = 'accepted'

This query could return like the following:

http://i.imgur.com/5cJ5v.png

So for each opportunity_id and user_id returned i'd like to then do:

UPDATE user_hours
SET    completed_hours = agreed_hours,
       hours_committed = 'completed'
WHERE  opportunity_id = {opportunity_id}
       AND user_id = {user_id}
       AND hours_committed = 'accepted'
       AND completed_hours IS NULL

Note that {opportunity_id} and {user_id} would need to be looped at this point (see screenshot) because we need to go through each user on each opportunity.

Then for each updated record i'd need to then get the total hours like:

// Get hours they have done to send to statistics data table
SELECT sum(completed_hours) FROM user_hours WHERE user_id = {user_id} AND opportunity_id = {opportunity_id} 

// Get the completed hours total somehow as a variable
$completed_hours = (from result above)

// Commit stats
UPDATE hours_statistics SET completed_hours = (completed_hours+$completed_hours)
WHERE user_id = {user_id} AND opportunity_id =  {opportunity_id} 

Could anyone help write this as a procedure or a trigger of some kind or help me in the right direction to get a starting point for looping over this stuff? Manually the querying works, just need to be looped / automatic for a stats update to run.

Was it helpful?

Solution

You can create a trigger to update hours_statistics whenever user_hours is updated (you may also want to add similar triggers for INSERT and DELETE operations, depending on your application logic).

Assuming that a UNIQUE key has been defined on hours_statistics.(user_id, opportunity_id) one can use INSERT ... ON DUPLICATE KEY UPDATE within the trigger:

CREATE TRIGGER foo AFTER UPDATE ON user_hours FOR EACH ROW
  INSERT INTO hours_statistics (user_id, opportunity_id, completed_hours) VALUES
    (OLD.user_id, OLD.opportunity_id, -OLD.completed_hours),
    (NEW.user_id, NEW.opportunity_id, +NEW.completed_hours)
  ON DUPLICATE KEY UPDATE
    completed_hours = completed_hours + VALUES(completed_hours);

Then you can use a single UPDATE statement (using the multiple-table syntax to join user_hours with user_calendar) to perform all of the updates on user_hours in one go, which will cause the above trigger to update hours_statistics as desired:

UPDATE user_hours JOIN user_calendar USING (user_calendar_id, opportunity_id)
SET    user_hours.completed_hours = agreed_hours,
       user_hours.hours_committed = 'completed'
WHERE  user_hours.hours_committed = 'accepted' 
   AND user_hours.completed_hours IS NULL
   AND user_calendar.date_start = CURRENT_DATE();
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top