Récupérer des enregistrements uniques à partir de tables jointes pouvant générer plusieurs enregistrements
-
03-07-2019 - |
Question
J'ai une table d'étudiant et une table d'inscription; un étudiant peut avoir plusieurs enregistrements d’inscription qui peuvent être actifs ou inactifs.
Je souhaite obtenir une sélection comportant un seul enregistrement d'élève et un indicateur indiquant si cet élève a des effectifs actifs.
J'ai pensé faire cela dans un fichier UDF en ligne qui utilise l'identifiant de l'étudiant dans une jointure de la table d'inscription, mais je me demande s'il existe une meilleure façon de le faire dans une seule instruction select.
L’appel UDF peut ressembler à quelque chose comme:
Select Student_Name,Student_Email,isEnrolled(Student_ID) from Student
À quoi pourrait ressembler l'alternative - avec une instruction SQL -?
La solution
select Student_Name,
Student_Email,
(select count(*)
from Enrollment e
where e.student_id = s.student_id
) Number_Of_Enrollments
from Student e
obtiendra le nombre d'inscriptions, ce qui devrait aider.
Autres conseils
Pourquoi ne pas rejoindre une sélection secondaire? Contrairement aux autres solutions, cela ne déclenche pas une sous-requête pour chaque ligne renvoyée, mais rassemble les données d'inscription pour tout le monde en même temps. La syntaxe n'est peut-être pas tout à fait correcte, mais vous devriez en avoir l'idée.
SELECT
s.student_name,
s.student_email,
IsNull( e.enrollment_count, 0 )
FROM
Students s
LEFT OUTER JOIN (
SELECT
student_id,
count(*) as enrollment_count
FROM
enrollments
WHERE
active = 1
GROUP BY
student_id
) e
ON s.student_id = e.student_id
La sélection parmi les inscriptions peut également être refaite en tant que fonction qui renvoie une table sur laquelle vous pourrez vous joindre.
CREATE FUNCTION getAllEnrollmentsGroupedByStudent()
RETURNS @enrollments TABLE
(
student_id int,
enrollment_count int
) AS BEGIN
INSERT INTO
@enrollments
(
student_id,
enrollment_count
) SELECT
student_id,
count(*) as enrollment_count
FROM
enrollments
WHERE
active = 1
GROUP BY
student_id
RETURN
END
SELECT
s.student_name,
s.student_email,
e.enrollment_count
FROM
Students s
JOIN
dbo.getAllEnrollmentsGroupedByStudent() e
ON s.student_id = e.student_id
Modifier:
Renze de Waal a corrigé mon mauvais SQL!
Essayez quelque chose comme ça:
SELECT Student_Name, Student_Email, CAST((SELECT TOP 1 1 FROM Enrollments e WHERE e.student_id=s.student_id) as bit) as enrolled FROM Student s
Je pense que vous pouvez également utiliser la déclaration exist dans le select mais pas positif
essayez d’éviter d’utiliser des udfs ou des sous-requêtes, ce sont des performances qui tuent. sinon, banjolity semble être une bonne solution, car elle utilise une table dérivée au lieu d’un fichier UDF ou subselect.
select students.name,
decode(count(1), 0, "no enrollments", "has enrollments")
from students, enrollments
where
students.id = enrollments.sutdent_id and
enrollments.is_active = 1 group by students.name
Bien sûr, remplacez le décodage par une fonction utilisée par votre base de données (ou une instruction case).