I Have a table called EMPLOYEE
| employee_id | name | supervisor_id |
| 123 | Ace Ven | NULL |
| 124 | Ben Agent | 123 |
| 125 | Sam Marks | 123 |
| 126 | Bob Teabag | 125 |
| 127 | Matthew Smith | 125 |
| 128 | Toby McQuire | 123 |
I am trying to find the supervisors and list the amount of employees they have. as you can see the supervisor_id is the same as employee_id. Should come out like this
name | total_employees |
Ace Ven | 3 |
Sam Marks | 2 |
I tried
SELECT supervisor_id, name, count(supervisor_id) AS total_employees FROM EMPLOYEE GROUP BY name HAVING (total_employees > 0);
which didn't work at all (sorry about the format, can't seem to get it to work).
Subquery counts how many records/employees are for each supervisor_id, then this result simply joined table again for retrieving their names:
select your_table.name, t.total_employees from your_table
inner join
(select supervisor_id, count(*) as total_employees from your_table where supervisor_id is not null group by supervisor_id) t
on your_table.employee_id = t.supervisor_id
A simple join will suffice...
Select x.name
, count(*) total
from employee x
join employee y
on y.supervisor_id = x.employee_id
group
by x.employee_id;
Related
I have a sample table below,
+-------------+-------------+-------------+----------+------------+---------------------------------+----------+---------------+
| employee_id | first_name | last_name | email | joined_date| title | salary | supervisor_id |
+-------------+-------------+-------------+----------+------------+---------------------------------+----------+---------------+
| 100 | John | King | EM1 | 1984-06-17 | CEO | 14000.00 | NULL |
| 101 | Leona | Kochhar | EM2 | 1993-09-21 | COO | 10000.00 | 100 |
| 102 | Lex | De Haan | EM3 | 1992-01-13 | CFO | 9000.00 | 100 |
| 103 | Alexander | Hunold | EM4 | 2001-04-03 | Gamer | 5000.00 | 102 |
| 104 | Dave | William | EM5 | 2002-05-21 | Gamer | 2000.00 | 103 |
| 105 | David | Austin | EM6 | 2002-06-25 | Gamer | 2800.00 | 103 |
| 106 | Valli | Longwind | EM7 | 2002-02-43 | Gamer | 2800.00 | 103 |
Certain employees are supervisors to other employees in this table. Do note that supervisor_id is the employee_id.
I am tasked to only use SELECT statement to get the employee_id, first_name, salary of the supervisors and the total number of employee under the supervisor.
In my mind, I know that I will need to use some sort of grouping and count. First, COUNT number of employees under each supervisor and second to GROUP BY supervisor ID. I managed to get the output using the simple COUNT and GROUP BY using this query:
SELECT employee_id, COUNT(supervisor_id)
FROM EMPLOYEE
GROUP BY supervisor_id;
This output the supervisor_id and number of employees under the supervisor_id. Which is:
+---------------+----------------------+
| supervisor_id | COUNT(supervisor_id) |
+---------------+----------------------+
| NULL | 0 |
| 100 | 2 |
| 101 | 0 |
| 102 | 0 |
| 103 | 3 |
*Table above slightly modified - this is a sample output
As mentioned, supervisor_id is the employee_id of the employee within the same table. My problem is that I am unable to get this table to display the employee_id, first_name and salary together with the COUNT column. The end result must show the employee_id (linked to supervisor_id), first_name, salary, COUNT.
I have tried this
SELECT employee_id, first_name, salary, COUNT(supervisor_id)
FROM EMPLOYEE
GROUP BY employee_id, first_name, salary, supervisor_id;
But this just returns the original table.
Also when I tried this
SELECT employee_id, first_name, salary, COUNT(supervisor_id)
FROM EMPLOYEE
GROUP BY supervisor_id;
It returns error "Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column" which according to online is how I craft my query (can't mix aggregated and non-aggregated column?).
Can anyone guide me on this? Thanks.
I guess you just need self LEFT JOIN here:
https://www.db-fiddle.com/f/miLeekBXxoiVV1SxuTYc2c/0
SELECT s.employee_id, s.first_name, s.last_name, s.salary, COUNT(e.employee_id)
FROM employee s
LEFT JOIN employee e
ON e.supervisor_id = s.employee_id
GROUP BY s.employee_id, s.first_name, s.last_name, s.salary;
By the way, you've mentioned in comment that you want to use HAVING COUNT() = 0. You should better not use HAVING for this purpose but just change this query to INNER JOIN. It will do the same but more efficient way.
https://www.db-fiddle.com/f/gM6q1UyagrZ4e1EHRvJ1NU/0
Please try this
SELECT E1.supervisor_id,count(E2.supervisor_id) FROM `EMPLOYEE` AS E1
LEFT JOIN (select supervisor_id FROM EMPLOYEE GROUP BY
supervisor_id) AS E2 ON E1.supervisor_id = E2.supervisor_id
GROUP BY E1.supervisor_id
I have a PostgreSQL database linked to a Drill instance.
Whenever I am trying to join 2 tables which both have a column name and whenever I want to select this name Drill selects the wrong name column. What am I doing wrong?
Given the following 2 tables:
Department
| id | name |
|----|------|
| 1 | A |
| 2 | B |
Employee
| id | name | dept | salary |
|----|------|------|--------|
| 1 | U | 1 | 100 |
| 2 | V | 1 | 75 |
| 3 | W | 1 | 120 |
| 4 | X | 2 | 95 |
| 5 | Y | 2 | 140 |
| 6 | Z | 2 | 55 |
Running
select employee.name, employee.salary
from employee
inner join department on employee.dept = department.id
where department.name = 'A'
returns
| name | salary |
|------|--------|
| A | 100 |
| A | 75 |
| A | 120 |
Running
select dept.name, employee.salary
from employee
inner join department on employee.dept = department.id
where department.name = 'A'
returns
| name | salary |
|------|--------|
| null | 100 |
| null | 75 |
| null | 120 |
What does work, but seems very silly to me, is:
select dept.name, employee.salary
from employee
inner join (select id, name as deptname from department) as department on employee.dept = department.id
where department.deptname = 'A'
This seems to be because you use
select dept.name, [...]
But you have never assigned an alias for the table department (department AS dept). Hence
select department.name, [...]
should yield the value you are looking for.
I'm trying, in a single query, to get an entire set of rows when only one of those rows meets certain criteria. In the case below, I want to do a query for Mike Smith. If I find Mike Smith has taken a test (by test_id) then I want to include all the results for that test_id. So a successful query would return the first 7 rows. Is this possible without running multiple queries? Below is the example entire contents of my table.
I can't use
Select * where first_name = 'Mike';
as this will only return Mike's test scores;
I don't know how to select all test scores (for multiple tests) when I have a result for Mike.
+------------+------------+-----------+-------+------+
| test_id | first_name | last_name | class | rank |
+------------+------------+-----------+-------+------+
| 1 | John | Doe | 2012 | 1 |
+------------+------------+-----------+-------+------+
| 1 | Jack | Smith | 2014 | 50 |
+------------+------------+-----------+-------+------+
| 1 | Mike | Smith | 2014 | 60 |
+------------+------------+-----------+-------+------+
| 2 | Mike | Smith | 2014 | 70 |
+------------+------------+-----------+-------+------+
| 2 | John | Smith | 2014 | 80 |
+------------+------------+-----------+-------+------+
| 3 | Jake | Smith | 2014 | 80 |
+------------+------------+-----------+-------+------+
| 3 | Mike | Smith | 2014 | 90 |
+------------+------------+-----------+-------+------+
| 4 | Jake | Smith | 2014 | 78 |
+------------+------------+-----------+-------+------+
Use the EXISTS clause, eg
SELECT * FROM `test_table` a WHERE EXISTS (
SELECT 1 FROM `test_table` b
WHERE first_name = 'Mike'
AND last_name = 'Smith'
AND b.test_id = a.test_id
)
Alternatively, you can INNER JOIN the table to itself, eg
SELECT a.* FROM `test_table` a
INNER JOIN `test_table` b
ON a.test_id = b.test_id
WHERE b.first_name = 'Mike' AND b.last_name = 'Smith'
Demo here - http://sqlfiddle.com/#!2/c8646/1
I think this might be what you're after:
SELECT *
FROM test_scores
WHERE test_id IN
(
SELECT test_id
FROM test_scores
WHERE first_name = 'Mike' AND last_name = 'Smith'
GROUP BY test_id
)
Note: I just assumed the table name was 'test_scores'
EDIT VERSION
EMPLOYEE TABLE
|ID | employee_id | Name |
| 1 | 123 | John Richard |
| 2 | 554 | Daniel Domingo |
educational background
|ID | employee_id | School/institute | date graduated |
| 1 | 123 | highschool | 2007 |
| 2 | 123 | college | 2011 |
| 3 | 554 | college | 2010 |
| 4 | 554 | masteral | 2013 |
job title
|ID | employee_id | Job description |
| 1 | 123 | Free lancer |
| 2 | 554 | admin assistant |
i need to select the latest date info of the employee's educational background
the result would be
result query
|ID | employee_id | Name | Job title | year_graduated | school_institute |
| 1 | 123 | John Richard | Free Lancer | 2011 | college |
| 2 | 554 | Daniel Domingo | Admin Assistant | 2013 | masteral |
Try this:
SELECT *
FROM (SELECT * FROM tableA ORDER BY employee_id, date_graduated DESC) A
GROUP BY employee_id
OR
SELECT a.*
FROM tableA a
INNER JOIN (SELECT employee_id, MAX(date_graduated) maxDate
FROM tableA GROUP BY employee_id
) b ON a.employee_id = b.employee_id AND a.date_graduated = b.maxDate
SELECT employee_id ,MAX([date graduated]) FROM Table GROUP BY [employee_id]
The result is
employee_id | date graduated
----------------------------
123 | 2011
554 | 2013
Subquery will return the maximum date for every employee, you should then join this subquery with your table to return the full row:
SELECT yourtable.*
FROM
yourtable INNER JOIN (SELECT employee_id, MAX(`date graduated`) max_date
FROM yourtable
GROUP BY employee_id) m
ON yourtable.employee_id = m.employee_id
AND yourtable.`date graduated` = m.max_date
for employee 123
SELECT * FROM `your_table`
WHERE employee_id=123
ORDER BY date_graduated DESC LIMIT 1
for employee 554
SELECT * FROM `your_table`
WHERE employee_id=554
ORDER BY date_graduated DESC LIMIT 1
SELECT *
FROM t
GROUP BY employee_id
HAVING date_graduated=max(date graduated)
and you'll get the desired result
i have 3 tables, the employee table, educational background and job_title,
i need to join the 3 tables and select the latest year the employee is graduated. the result query i need is listed below.
EMPLOYEE TABLE
|ID | employee_id | Name |
| 1 | 123 | Jewel Brin |
| 2 | 554 | Donna Ferry |
| 3 | 853 | Ricky David |
educational background
|ID | employee_id | School/level | date graduated |
| 1 | 123 | highschool | 2007 |
| 2 | 123 | college | 2011 |
| 3 | 554 | college | 2010 |
| 4 | 554 | masteral | 2013 |
job title
|ID | employee_id | Job description |
| 1 | 123 | Free lancer |
| 2 | 554 | admin assistant |
| 3 | 853 | Support Admin |
i need to select the latest date info of the employee's educational background
the result would be:
result query
|ID | employee_id | Name | Job title | year_graduated | school_institute |
| 1 | 123 | Jewel Brin | Free Lancer | 2011 | college |
| 2 | 554 | Donna Ferry | Admin Assistant | 2013 | masteral |
| 3 | 853 | Ricky David | Support Admin | Null | Null
Forgot to mention, this is MySQL :)
SELECT e.employee_id, Name, `Job description` AS `Job title`, year_graduated, school_institute
FROM `employee` e
INNER JOIN job_title j ON j.employee_id = e.employee_id
LEFT JOIN (SELECT ID, `School/level` AS school_institute, employee_id, `date graduated` AS year_graduated FROM `educational background` b
INNER JOIN (
SELECT ID, MAX(`date graduated`) AS max_date FROM `educational background` GROUP BY employee_id
) b2
ON b2.max_date = b.year_graduated AND b2.ID = b.ID
) bb ON bb.employee_id = e.employee_id
In SQL Server :-
Select *
from
(
Select e.ID,e.employee_ID,e.Name,
b.Level,j.[Job description],
rn = row_number()
over (partition by e.Employee_ID order by [date graduated] desc)
From Employee e
left join Background b
on e.Employee_ID = b.Employee_ID
left join Jobtitle j
on j.Employee_ID = b.Employee_ID
)a
where a.rn=1
SQL FIDDLE
For Mysql you can try this
SELECT DISTINCT
e.employee_id,
e.Name,
j.Job_description,
eb.year_graduated,
eb.level
FROM
EMPLOYEE e
LEFT JOIN
(SELECT
*,
MAX(t.date_graduated) year_graduated
FROM
(SELECT * FROM Background ORDER BY date_graduated DESC) t
GROUP BY employee_id) eb
ON (e.employee_id = eb.employee_id)
LEFT JOIN JobTitle j
ON (e.employee_id = j.employee_id)
See Fiddle Demo