Pregunta

Tengo una mesa de estudiantes y una mesa de inscripción; un estudiante puede tener varios registros de inscripción que pueden estar activos o inactivos.

Quiero obtener una selección que tenga un solo registro de estudiante y un indicador de si ese estudiante tiene inscripciones activas.

Pensé en hacer esto en una UDF en línea que usa la identificación del estudiante para unirse a la tabla de inscripción, pero me pregunto si hay una mejor manera de hacerlo en una sola declaración de selección.

La llamada UDF podría verse algo así como:

Select Student_Name,Student_Email,isEnrolled(Student_ID) from Student

¿Cuál podría ser la alternativa, con una declaración SQL?

¿Fue útil?

Solución

select  Student_Name,
        Student_Email,
        (select count(*) 
         from Enrollment e 
         where e.student_id = s.student_id
        ) Number_Of_Enrollments 
 from Student e

obtendrá el número de inscripciones, lo que debería ayudar.

Otros consejos

¿Por qué no unirse a una selección secundaria? A diferencia de otras soluciones, esto no está activando una subconsulta por cada fila devuelta, sino que recopila los datos de inscripción para todos a la vez. La sintaxis puede no ser del todo correcta, pero debería tener una idea.

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 selección de inscripciones también se podría rehacer como una función que devuelve una tabla para que se una.

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

Editar:
Renze de Waal corrigió mi mal SQL!

Prueba algo como esto:

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

Creo que también puedes usar la declaración de existencia en la selección pero no en la positiva

intenta evitar el uso de udfs o subconsultas, son asesinos de rendimiento. Banjolity parece tener una buena solución de lo contrario porque utiliza una tabla derivada en lugar de un UDF o una subselección.

  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

Por supuesto, reemplace la decodificación con una función que usa su base de datos (o, una declaración de caso).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top