我目前正在为学校开发一个数据库系统,该系统将与我们的预订系统配合使用,以便学生可以预订课程,我们可以更好地跟踪他们的活动。现在我面临一个复杂的问题,我想要做的是检查哪些学生合同是有效的,我可以通过使用以下功能来实现,但我想看看是否有更简单的方法来正确地做到这一点(除此之外)存储我可以在系统中计算的数据。)
如果合同有效,那么学生没有用尽他们购买的所有时间,购买的小时数是他们参加的教学课程长度加上他们错过的每个课程长度总和的总和。 (经过一定数量,如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
这些表包含这些数据列(忽略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
我意识到这可能会让问题变得复杂,但我只是想知道这是否真的是正确的做事方式,或者我是否应该在合同表中保存某种具有多个字段的字段小时数,并认为它总是准确的。
答案 0 :(得分:2)
似乎你可以做一些事情来改善这种情况
我猜这些并不总是一样的,并且与AD Hoc sql语句相比,拥有存储过程将允许缓存计划。这将允许您发送各种ID以获得所需的结果,并返回一个数据集,该数据集可以在简单转换为和Exce或Word表格的Web applciaiton中用于报告。
答案 1 :(得分:1)
这应该产生相同的功能并且更容易阅读:
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