MySQL, Find all employees of a "manager" - php

I have a "manager" that can be assigned to many locations and handles one department in every location. I want a query that can grab all of this:
http://sqlfiddle.com/#!2/33453c/1
In the example above (in the link) you can see I have calculated how many employees are in each department.
Managers and Employees are in a table named staff, I do not want the query to retrieve the manager record(s). So user_role = "Employee";
I run this as a raw query in laravel so I can retrieve them as objects:
$employees= DB::query('query goes in here')->get();
An example would be the manager with staff_id '5' get every employee that is in all of the locations and department the manager is part of if that makes sense?
My guess would be:
Pseudo
First Query SELECT ALL FROM staff, locations and departments where user_role = "employee"
Second Query SELECT ALL FROM staff, locations and departments where manager id=5
Remove all results that do not satisfy the second query but join both queries together?
Help would be greatly appreciated.

I think this is what you want. Left join the manager's department on employee's departments, and get the count of "employee" staff members in each of those departments (even if 0)
Below, shown for manager #2 (you could eliminate the where clause and group by manager id and dept id if you want to see all managers)
SELECT dept.name AS dept, loc.address1 AS loc, emp.*
FROM staff AS mgr
INNER JOIN department_staff AS mgr_dept
ON mgr_dept.staff_id = mgr.staff_id
INNER JOIN departments AS dept
ON mgr_dept.dept_id = dept.dept_id
INNER JOIN location_staff AS mgr_loc
ON mgr_loc.staff_id = mgr.staff_id
INNER JOIN locations AS loc
ON mgr_loc.loc_id = loc.loc_id
INNER JOIN (
SELECT emp.*, dept.dept_id, loc.loc_id
FROM staff AS emp
INNER JOIN department_staff AS dept
ON emp.staff_id = dept.staff_id
INNER JOIN location_staff AS loc
ON emp.staff_id = loc.staff_id
WHERE emp.user_role = "Employee"
) AS emp
ON emp.loc_id = mgr_loc.loc_id
AND emp.dept_id = mgr_dept.dept_id
WHERE mgr.staff_id = 2

Related

How do I inner join 2 SQL tables, but only take the first result from the second table?

I'm building a page where u can rent apartments and stuff,
and there are a lot of images of each of these apartments,
so I have made 2 tables. One with all apartments, and one with all images, that i connect to a specific apartment with a foreign key.
I want all the apartments, but i only want 1 image per apartment.
I have tried to do LIMIT 1, but then it limits apartments to 1 as well.
This is my code:
$sql = "SELECT bolig_boliger.id AS bolig_id, titel, areal, rooms,
indflytning, husleje, image
FROM bolig_boliger
INNER JOIN bolig_images ON bolig_boliger.id = bolig_images.bolig_id";
Join with a subquery that returns one row per apartment ID, instead of joining with the whole table.
SELECT b.id, b.titel, b.areal, b.rooms, b.indflytning, b.husleje, i.image
FROM bolig_boliger AS b
JOIN (
SELECT bolig_id, MAX(image) AS image
FROM bolig_images
GROUP BY bolig_id
) AS i ON b.id = i.bolig_id
One simple method s a correlated subquery. Of course, you have not shown the layout of the tables, so I have to speculate on what columns go where and how to identify the latest row. A reasonable guess is:
SELECT b.id AS bolig_id, titel, areal, rooms, indflytning, husleje, image
FROM bolig_boliger b INNER JOIN
bolig_images i
ON b.id = i.bolig_id
WHERE i.id = (SELECT MAX(i2.id) FROM bolig_images i2 WHERE i2.bolig_id = i.bolig_id)

mysql join where for 1 table

I have 2 tables, student and grades
student table contains id, name and date_of_birth
grades table contains id, student_id, grade and course
Actual table contain more data.
I have a query like
SELECT s.*, AVG(g.grade) as average_grade
FROM student s LEFT JOIN grade g ON s,id = g.student_id
WHERE g.course = 'mathematics' and s.id = 1
With this I could get the data i needed which are student details and the average grade, then come the problem where when the course = "mathematics" is not found in the grades table, the query will return NULL. My question is, is there a way for me to get the s.id = 1 details together with NULL average instead of all NULL value?
I would prefer if it is able to do it with 1 query, as because in my current I am using subquery and it takes very long to get the data. My main objective is to get more faster speed if you have better way instead of using 1 query feel free to comment your idea. In addition I have tried multiple query and sub query to get all the data but it all take too long.
Move your filter criteria for g.course = 'mathematics' in joining part
SELECT s.*, AVG(g.grade) as average_grade
FROM student s
LEFT JOIN grade g ON s.id = g.student_id AND g.course = 'mathematics'
WHERE s.id = 1
Your query produces result as inner join not left because putting g.course = 'mathematics in where clause turns your left join to inner join, Moving this part in on clause will still return data from student table if there were no rows found from grade table with course = 'mathematics'
If the course is not 'mathematics' you would still get the student data if you put it like this.
SELECT s.*, AVG(g.grade) as average_grade
FROM student s LEFT JOIN grade g ON s,id = g.student_id
WHERE (g.course = 'mathematics' AND s.id = 1) OR s.id = 1

How to replace two user id columns with names?

I have a table with two columns.
created_by | assigned_to
One is the person who create a "to do card", the other column is the person who is assigned to do it.
The columns are filled with id, for example; (1,2,3).
My question is how can i replace this id with the names that are saved in another table.
by far this is what i got.
SELECT tickets.*, users.Name, users.LastName
FROM tickets
LEFT JOIN users ON tickets.assigned_to = users.uid
AND tickets.id_usuario = users.uid
but when i try to print the name of the persona
Created by: <?= query['Name']; ?>
Assigned to: <?= query['Name']; ?>
but i got the same name in both columns.
Your current query only joins to users when the creator and assigned-to user ID are the same.
You'll need to join to your users table twice to retrieve the separate records. You do this by adding more joins...
SELECT
c_users.Name as created_by_name,
c_users.LastName as created_by_last_name,
a_users.Name as assigned_to_name,
a_users.LastName as assigned_to_last_name
FROM tickets t
INNER JOIN users c_users
ON t.created_by = c_users.uid
-- or t.id_usuario = c_users.uid, it is not clear from your question
INNER JOIN users a_users
ON t.assigned_to = a_users.uid
I've used INNER JOIN instead of LEFT JOIN as it doesn't seem feasible that you'd have broken relationships between the two tables.

display data together from 2 different SQL table

I need to display details from 2 different tables
Table 1- user table
Table 2-bicycle table
I can show a list of users and bicycle.
But can't show a list that show which bicycle belongs to who.
Bicycle table,
user table
You need to use a LEFT JOIN. The query below will connect your user table to your bicycle table based on the userIDand return all of the bicycle and user fields
SELECT b.*, u.*
FROM registered_users u
LEFT JOIN registered_bicycle b ON (u.userID = b.userID)
If you want specific bicycle fields just prefix them with b. Example:
SELECT b.brand, b.model, b.color...
Click on SQL tab and type this:
SELECT * FROM `registered_bicycle` JOIN `registered_users` ON `registered_users`.`userID` = `registered_bicycle`.`userID`
and run it
You have to make a foreign key from user_table to bicycle_table like this.
user_table has user_id = user_1,name=John Richard
bicycle_table has user_id = user_1,description = Bicycle1
to fetch the data:
select a.user_id, a.name,b.description from
(select user_id, name from user_table) as a
left join
(select user_id,description from bicycle_table) as b
on a.user_id = b.user_id

MySQL ISNULL with INNER JOIN

I have 2 tables: "shares" and "pending_share_changes". The "shares" table has the following columns:
share_ID, asset_ID, member_ID, percent_owner, is_approved
pending_share_changes has the following columns:
share_change_ID, asset_ID, member_ID, percent_owner, is_approved, requested_by
I have a form (php) which lists the pending changes which the members have to approve or deny. Everything works fine unless the member has no existing shares, which means there is no record in the "shares" table for them. The query I am using to view the pending share changes is as follows:
SELECT p.share_change_ID, assets.asset_desc, assets.asset_value, shares.percent_owner AS
percent_owner_old, p.percent_owner
FROM pending_share_changes as p
inner join assets on assets.asset_ID = p.asset_ID
inner join shares on shares.asset_ID = p.asset_ID AND shares.member_ID = p.member_ID
INNER JOIN orgs ON orgs.org_ID = assets.org_ID
WHERE orgs.org_ID = '$org_ID' AND p.member_ID = '$member_ID' AND p.is_approved = '0'
I tried using IFNULL(shares.percent_owner, 0) AS percent_owner_old but that didn't work. The query returns no results. I would like to have the percent_owner_old column display a "0" if there is no record in the shares table.
Thanks.
Try changing your join to shares from an INNER JOIN to a LEFT JOIN.
SELECT ....
FROM pending_share_changes p
....
LEFT JOIN shares ON shares.asset_ID = p.asset_ID AND shares.member_ID = p.member_ID
This means "for every member_ID and asset_ID in p, join it to the matching row in shares. If the member_ID/asset_ID exists in p but not shares, make a row anyway and set the corresponding values to NULL".
The INNER JOIN means to only show joined rows where the relevant record exists in both tables.
Then you can combine with the IFNULL(shares.percent_owner,0) AS percent_owner_old.

Categories