Комплексная реализация оператора SQL - PullRequest
3 голосов
/ 26 сентября 2011

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

Если контракт действителен, то учащийся не израсходовал все приобретенные часы, приобретенные часы - это сумма продолжительности обучения, которое они посетили, добавленок сумме длин каждого класса, который они пропустили, но забронировали (после определенного числа, такого как 3 или 5).Я могу сделать это с помощью следующего запроса, но я чувствую, что должен быть более простой способ:

SELECT
    level.name
FROM
    (
        SELECT
            contract.level_package_id,
            contract_class_hours.hours_purchased,
            (
                SELECT
                    isnull(sum(DATEPART(hh, class.end_date - class.start_date)), 0)
                FROM
                    booking
                    JOIN class ON class.id = booking.class_id
                WHERE
                    booking.booking_state_id = 3
                    AND booking.contract_id = contract.id
            ) AS time_attended,
            (
                SELECT 
                    isnull(sum(absent_class_lengths.length), 0)
                FROM
                    (
                        SELECT
                            DATEPART(hh, class.end_date - class.start_date) AS length,
                            row_number() OVER (ORDER BY class.start_date) AS rn
                        FROM
                            booking
                            JOIN class ON class.id = booking.class_id
                        WHERE
                            student_id = 5
                            AND booking_state_id = 4
                            AND booking.contract_id = contract.id
                    ) absent_class_lengths
                WHERE 
                    rn > contract_class_hours.absences_allowed
            ) as time_absent
        FROM
            contract
            JOIN contract_class_hours ON contract_class_hours.contract_id = contract.id
    ) test
    JOIN level_package_level ON level_package_level.level_package_id = test.level_package_id
    JOIN level ON level.id = level_package_level.level_id
WHERE
    test.time_absent + test.time_attended < test.hours_purchased
    AND level.study_type_id = 2
  • booking.state_id = 3 означает, что студент посещал класс
  • booking.state_id= 4 означает, что ученик отсутствовал
  • level.study_type_id = 2 - это просто предмет курса

Таблицы содержат столбцы данных, подобные этим (игнорируйте level_id, это просто нужное мне значениевернуться):

CLASS
    id - int
    end_date - datetime
    start_date - datetime

BOOKING
    id - int
    class_id - int
    student_id - int
    booking_state_id - smallint

BOOKING_STATE
    id - int
    state - varchar(20) [absent, attended]

CONTRACT
    id - int
    student_id - int
    level_id - int
    hours_purchased - smallint
    absenses_allowed - smallint

STUDENT
    id - int

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

Ответы [ 2 ]

2 голосов
/ 13 октября 2011

Похоже, вы могли бы сделать несколько вещей, чтобы улучшить ситуацию

  1. Создать представление с использованием некоторого кода
  2. Используйте приведенный выше ответ для создания хранимой процедуры и выполните командужестко закодированные переменные идентификаторов WHERE class.student_id = 5 AND booking_state_id = 4

Я предполагаю, что они не всегда будут одинаковыми, и наличие хранимой процедуры позволит кэшировать план по сравнениюв AD Hoc SQL заявление.Это позволит вам отправлять различные идентификаторы, чтобы получить желаемые результаты, и возвращать набор данных, который можно использовать в веб-приложении для простого преобразования в таблицу Exce или Word для создания отчетов.

1 голос
/ 01 октября 2011

Это должно дать ту же функциональность и быть легче для чтения:

SELECT
   level.name
FROM contract
INNER JOIN contract_class_hours ON contract_class_hours.contract_id = contract.id
INNER JOIN level_package_level ON level_package_level.level_package_id = contract.level_package_id
INNER JOIN level ON level.id = level_package_level.level_id
Outer Apply(
    SELECT isnull(sum(DATEPART(hh, class.end_date - class.start_date)), 0) AS time_attended
    FROM booking
    INNER JOIN class ON class.id = booking.class_id
    WHERE booking.booking_state_id = 3
        AND booking.contract_id = contract.id
) T1
Outer Apply(
    SELECT snull(sum(absent_class_lengths.length), 0) AS time_absent
    FROM
    (
        SELECT DATEPART(hh, class.end_date - class.start_date) AS length,
            row_number() OVER (ORDER BY class.start_date) AS rn
        FROM booking
        INNER JOIN class ON class.id = booking.class_id
        WHERE class.student_id = 5
           AND booking_state_id = 4
           AND booking.contract_id = contract.id
    ) absent_class_lengths
    WHERE 
    rn > contract_class_hours.absences_allowed
) T2
WHERE T2.time_absent + T1.time_attended < contract_class_hours.hours_purchased
   AND level.study_type_id = 2
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...