Question

In a scenario where I have a table like so:

int id (PK)
int staff_id
int skill_id
bit mainskill

I want to select only ONE record for each staff member (represented by staff_id) listing their main skill as represented by a (1) in mainskill. If no main skill is present, I want to return any of the skill records for that staff member. For example:

id   staff_id   skill_id   mainskill
1    1          24         1
2    1          55         0
3    1          7          0
4    4          24         0
5    4          18         0
6    6          3          0
7    6          18         1

The query should return:

id   staff_id   skill_id   mainskill
1    1          24         1
4    4          24         0
7    6          18         1

I've tried various combinations of grouping, DISTINCT etc but can't get the output I'm after. Any help appreciated.

Was it helpful?

Solution

SQL Server 2005+, Using CTE:


WITH rows AS (
  SELECT t.id,
         t.staff_id,
         t.skill_id,
         t.mainskill,
         ROW_NUMBER() OVER (PARTITION BY t.staff_id ORDER BY t.mainskill DESC) AS rank
    FROM TABLE t)
  SELECT r.id,
         r.staff_id,
         r.skill_id,
         r.mainskill
    FROM rows r
   WHERE r.rank = 1
ORDER BY r.staff_id

SQL Server 2005+, Non-CTE Equivalent:


  SELECT r.id,
         r.staff_id,
         r.skill_id,
         r.mainskill
    FROM (SELECT t.id,
                 t.staff_id,
                 t.skill_id,
                 t.mainskill,
                 ROW_NUMBER() OVER (PARTITION BY t.staff_id ORDER BY t.mainskill DESC) AS rank
            FROM TABLE t) r
   WHERE r.rank = 1
ORDER BY r.staff_id

Both use ROW_NUMBER, which is only available since SQL Server 2005.

OTHER TIPS

If you concatenate the mainskill on the front of the skillid, max will give you either the mainskill or one other where mainskill doesn't exist.

SELECT t.id, t.staff_id, t.skill_id, t.mainskill, FROM TABLE t WHERE CAST(t.mainskill As Varchar(5))+'-'+ Cast(t.skill_id as varchar(5)) IN (SELECT MAX(CAST(t.mainskill As Varchar(5))+'-'+ Cast(t.skill_id as varchar(5))) FROM TABLE t GROUP BY t.staff_id)

MySQL

select * from staff_skill;

id         staff_id   skill_id   mainskill  
---------- ---------- ---------- ---------- 
1          1          24         1          
2          1          55         0          
3          1          7          0          
4          4          24         0          
5          4          18         0          
6          6          3          0          
7          6          18         1          

7 rows selected


select * from staff_skill x
where skill_id =
(select y.skill_id from staff_skill y
where y.staff_id = x.staff_id 
order by y.mainskill desc, y.skill_id desc limit 1);

id         staff_id   skill_id   mainskill  
---------- ---------- ---------- ---------- 
1          1          24         1          
4          4          24         0          
7          6          18         1          

3 rows selected

- Ian

Oracle

how about:

(staff_skill is your table)

select * from staff_skill x where
skill_id =
(select skill_id from 
(select * from staff_skill 
order by mainskill desc, skill_id desc)
where staff_id = x.staff_id and rownum = 1);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top