开发者

SQL - select distinct records in one field with highest records from another field

开发者 https://www.devze.com 2022-12-18 11:38 出处:网络
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 s

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          5开发者_如何学编程5         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.


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.


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);
0

精彩评论

暂无评论...
验证码 换一张
取 消