Récupérer des enregistrements uniques à partir de tables jointes pouvant générer plusieurs enregistrements

StackOverflow https://stackoverflow.com/questions/608451

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 -?

Était-ce utile?

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).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top