3
WITH 
Emp(DName, EName, Role) AS (
     VALUES ('D1','E11', 'Role1'), 
            ('D1','E11', 'Role2'),
            ('D1','E12', 'Role1'), 
            ('D2','E12', 'Role1')
) 

For each department, fetch the number of individual employees for each role.
The output should be:

#_of_Role1_Employees; #_of_Role2_Employees
2; 1
1; 0
Erwin Brandstetter
  • 605,456
  • 145
  • 1,078
  • 1,228
Gopal
  • 1,372
  • 2
  • 16
  • 32

3 Answers3

2
WITH 
Emp(DName, EName, Role) AS (
     VALUES ('D1','E11', 'Role1'), 
            ('D1','E11', 'Role2'),
            ('D1','E12', 'Role1'), 
            ('D2','E12', 'Role1')
)
select
    dname "Dname",
    count(role = 'Role1' or null) "Role1",
    count(role = 'Role2' or null) "Role2"
from emp
group by dname
;
 Dname | Role1 | Role2 
-------+-------+-------
 D1    |     2 |     1
 D2    |     1 |     0

Update

This should match the distinct requirement:

WITH
Emp(DName, EName, Role) AS (
     VALUES ('D1','E11', 'Role1'),
            ('D1','E11', 'Role2'),
            ('D1','E12', 'Role1'),
            ('D2','E12', 'Role1')
)
select
    dname "Dname",
    count(role = 'Role1' or null) "Role1",
    count(role = 'Role2' or null) "Role2"
from (
    select distinct *
    from emp
) s
group by dname
;
 Dname | Role1 | Role2 
-------+-------+-------
 D1    |     2 |     1
 D2    |     1 |     0
Clodoaldo Neto
  • 118,695
  • 26
  • 233
  • 260
0

Within the department Group, each employee row is to be checked for the role, and the distinct employee names are counted.

Select COUNT(Distinct(CASE WHEN Role = 'Role1' THEN EName END)) As "#_of_Role1_Employees",
       COUNT(Distinct(CASE WHEN Role = 'Role2' THEN EName END)) As "#_of_Role2_Employees"
from Emp
Group by DName
Gopal
  • 1,372
  • 2
  • 16
  • 32
0

The fact that there can be duplicate entries per (dname, ename, role) is indication for an over-simplified test case. I suspect the test case should really be:

CREATE TEMP TABLE emp(dname text, ename text, role text, col1 text);
INSERT INTO emp VALUES
    ('D1','E11', 'Role1', 'foo1')
   ,('D1','E11', 'Role2', 'foo2')
   ,('D1','E12', 'Role1', 'foo3')
   ,('D1','E12', 'Role1', 'foo4')
   ,('D2','E12', 'Role2', 'foo5');

Then @Clodoaldo's (otherwise fine) query would have to use:

SELECT DISTINCT dname, ename, role

instead of:

SELECT DISTINCT *

An alternative would be a crosstab query:

SELECT * FROM crosstab(
      $x$
      SELECT dname, role, count(DISTINCT ename)::int
      FROM   emp
      GROUP  BY dname, role
      $x$

      ,$y$SELECT DISTINCT role FROM emp ORDER BY 1$y$)
AS ct (dname text, "Role1" text, "Role2" int);

You need the tablefunc installed for this. More details for this query in this related answer:
PostgreSQL Crosstab Query

You have to list all possible roles in the column definition list.

Community
  • 1
  • 1
Erwin Brandstetter
  • 605,456
  • 145
  • 1,078
  • 1,228