Home > Blockchain >  What is the correct query for this question?
What is the correct query for this question?

Time:08-01

Tables Query

TABLES

users 
    id bigint
    first_name varchar(255)
    last_name varchar(255)
    email varchar(255) 

service_events
    id bigint
    name varchar(255)

service_logs
    id bigint
    approved tinyint
    user_id bigint(fk:users)
    service_event_id bigint(fk:service_events)
    deleted_at datetime(nullable)

service_log_days
    id bigint
    sevice_log_id bigint(fk:service_Logs)
    total_hours double

Question:

Return a table of users with the hour sum of their total approved, non-deleted service logs. Return a record for each student, not just those who have service log records. If a student doesn't have service logs that match the filters, they should have "0" value for their row. There should only be one row per student.

Example output table would look like:

first_name  last_name   email       total_hours
Student     One     [email protected]   0
Student     Two     [email protected]   135

I tried:

SELECT u.first_name, u.last_name, u.email, sld.total_hours
FROM users as u 
INNER JOIN service_log_days as sld 
ON ?????

What is the correct query?

CodePudding user response:

Without data example it is hard to answer , but try the following query:

SELECT u.first_name,
       u.last_name,
       u.email,
       COALESCE(sld.total_hours, 0)  as tot_hours
FROM users u    
LEFT JOIN  service_logs sl on sl.user_id=u.id   
INNER JOIN  service_log_days sld on sld.sevice_log_id=sl.id

For the part ,

Return a record for each student, not just those who have service log records. If a student doesn't have service logs that match the filters, they should have "0" value for their row. There should only be one row per student.

you need to use LEFT JOIN and COALESCE which the null values will be transormed to 0 instead.

Note if the data in service_log_days are repeated for a user change

COALESCE(sld.total_hours, 0) 

to

COALESCE(SUM(sld.total_hours), 0) 

and add u.first_name,u.last_name,u.email in the group by clause.

CodePudding user response:

Join the tables. Use outer joins, as a user may not have service logs or no hours associated. When outer joining the service logs, only join those rows that are approved (approved = 1) and not deleted (deleted_at is null). At last group by user and count.

select u.*, coalesce(sum(sld.total_hours), 0) as total
from users u
left outer join service_logs sl on sl.user_id = u.id
                               and sl.approved = 1
                               and sl.deleted_at is null
left outer join service_log_days sld on sld.sevice_log_id = sl.id
group by u.id
order by u.id;

CodePudding user response:

Given the images u posted, the join should be on the id, as it is the column stays the same between different tables. So it should be u.id == sld.id and remember to use the IFNULL function to replace the null value with 0 W3schools tutorial

  • Related