SQL - sélectionner des enregistrements distincts dans un champ avec plus d'un autre domaine les enregistrements
-
22-09-2019 - |
Question
Dans un scénario où j'ai une table comme ceci:
int id (PK)
int staff_id
int skill_id
bit mainskill
Je veux sélectionner un seul enregistrement pour chaque membre du personnel (représenté par Nom employé) l'inscription de leur compétence principale représentée par un (1) mainskill. Si aucune compétence principale est présent, je veux renvoyer les dossiers de compétence pour ce membre du personnel. Par exemple:
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
La requête doit revenir:
id staff_id skill_id mainskill
1 1 24 1
4 4 24 0
7 6 18 1
J'ai essayé différentes combinaisons de regroupement, etc DISTINCT mais ne peut pas obtenir la sortie que je suis après. Toute aide appréciée.
La solution
SQL Server 2005+, utilisant 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+, équivalent non-CTE:
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
ROW_NUMBER , qui est uniquement disponible depuis SQL Server 2005.
Autres conseils
Si vous concaténer le mainskill sur le devant de la SkillID, max vous donnera soit le mainskill ou un autre où mainskill n'existe pas.
SELECT t.id, t.staff_id, t.skill_id, t.mainskill, TABLEAU DE t OÙ CAST (t.mainskill Comme Varchar (5)) + '-' + Ensemble (t.skill_id comme varchar (5)) DANS (SELECT MAX (CAST (t.mainskill Comme Varchar (5)) + '-' + Ensemble (t.skill_id comme varchar (5))) à partir de TABLEAU t GROUPE PAR 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
Que diriez-vous:
(staff_skill est votre 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);