Получение отдельных записей из объединенных таблиц, которые могут создавать несколько записей

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

Вопрос

У меня есть стол для студентов и стол для зачисления;студент может иметь несколько записей о зачислении, которые могут быть активными или неактивными.

Я хочу получить выборку с одной записью учащегося и индикатором того, есть ли у этого учащегося активные зачисления.

Я думал сделать это во встроенной пользовательской функции, которая использует идентификатор студента при соединении с таблицей регистрации, но мне интересно, есть ли лучший способ сделать это в одном операторе выбора.

Вызов UDF может выглядеть примерно так:

Select Student_Name,Student_Email,isEnrolled(Student_ID) from Student

Как могла бы выглядеть альтернатива с одним оператором SQL?

Это было полезно?

Решение

select  Student_Name,
        Student_Email,
        (select count(*) 
         from Enrollment e 
         where e.student_id = s.student_id
        ) Number_Of_Enrollments 
 from Student 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

Выбор из регистраций также можно переделать в функцию, которая возвращает таблицу, к которой вы можете присоединиться.

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

Редактировать:
Ренце де Ваал исправил мой плохой SQL!

Попробуйте что-нибудь вроде этого:

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

Я думаю, вы также можете использовать оператор существования в выборе, но не в положительном

старайтесь избегать использования udfs или подзапросов, они снижают производительность.В противном случае у Banjoility, кажется, есть хорошее решение, поскольку он использует таблицу производных вместо UDF или подвыборки.

  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

Конечно, замените декодирование функцией, которую использует ваша база данных (или оператором случая).

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top