简体   繁体   中英

Trying to get a row count in a subquery

I have two tables, one is departments and the other is employees. The department id is a foreign key in the employees table. The employee table has a name and a flag saying if the person is part-time. I can have zero or more employees in a department. I'm trying to figure out out to get a list of all departments where a department has at least one employee and if it does have at least one employee, that all the employees are part time. I think this has to be some kind of subquery to get this. Here's what I have so far:

SELECT dept.name
    ,dept.id
    ,employee.deptid
    ,count(employee.is_parttime)
FROM employee
    ,dept
WHERE dept.id = employee.deptid
    AND employee.is_parttime = 1
GROUP BY employee.is_parttime

I would really appreciate any help at this point.

You must join (properly) the tables and group by department with a condition in the HAVING clause:

select d.name, d.id, count(e.id) total 
from dept d inner join employee e
on d.id = e.deptid 
group by d.name, d.id
having total = sum(e.is_parttime)

The inner join returns only departments with at least 1 employee.
The column is_parttime (I guess) is a flag with values 0 or 1 so by summing it the result is the number of employees that are part time in the department and this number is compared to the total number of employees of the department.

As a preliminary aside , I recommend expressing joins with the JOIN keyword, and segregating join conditions from filter conditions. Doing so would make the original query look like so:

select dept.name, dept.id, employee.deptid, count(employee.is_parttime)
from employee
  join dept on dept.id = employee.deptid
where employee.is_parttime = 1
group by employee.is_parttime

It doesn't make much practical difference for inner joins, but it does make the structure of the data and the logic of the query a bit clearer. On the other hand, it does make a difference for outer joins, and there is value in consistency.


As for the actual question, yes, one can rewrite the original query using a subquery or an inline view to produce the requested result. (An "inline view" is technically what one should call an embedded query used as a table in the FROM clause, but some people lump these in with subqueries.)

Example using a subquery

select dept.name, dept.id
from dept
where dept.id in (
    select deptid
    from employee
    group by deptid
    having count(*) == sum(is_parttime)
  )

Example using an inline view

select dept.name, dept.id
from dept
  join (
    select deptid
    from employee
    group by deptid
    having count(*) == sum(is_parttime)
  )  pt_dept
  on dept.id = pt_dept.deptid

In each case, the subquery / inline view does most of the work. It aggregates employees by department, then filters the groups ( HAVING clause) to select only those in which the part-time employee count is the same as the total count. Naturally, departments without any employees will not be represented. If a list of department IDs would suffice for a list of departments, then that's actually all you need. To get the department names too, however, you need to combine that with data from the dept table, as demonstrated in the two example queries.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM