我正在创建一个系统,使用SQL Server Management Studio显示学生的时间表并将其链接到Visual Studio程序(这与我的问题无关但只是添加上下文),但是我的数据库表存在一个主要问题目前,我需要一些帮助。
我的项目的基本背景是有3个表,Lesson
,Student
和Subject
。这些表格中填充了小型测试样本数据集。
Lesson
表:
LessonID DayOfWk PeriodValue SubjectID Room blockLessonIsIn
-------------------------------------------------------------------
1 Mon 2 1 G8 2
2 Mon 3 1 G8 2
3 Mon 4 1 G8 2
4 Mon 5 2 N5 1
5 Tue 1 3 SF5 4
6 Tue 3 2 N7 1
7 Wed 1 3 SF5 4
8 Wed 2 1 H9B 2
9 Wed 5 1 G8 2
10 Thu 1 3 SF4 4
11 Thu 3 2 N7 1
12 Thu 5 3 SF5 4
13 Fri 1 3 SF5 4
14 Fri 2 1 G8 2
15 Fri 3 1 H9B 2
16 Fri 4 2 SP2 1
17 Mon 1 5 H1 1
18 Tue 5 5 H1 1
19 Thu 3 5 H1 1
20 Fri 4 5 H1 1
21 Wed 4 4 S1 3
22 Fri 5 4 S1 3
23 Tue 1 2 N1 4
24 Tue 2 2 N1 4
25 Wed 1 2 N1 4
26 Thu 1 2 N1 4
27 Thu 4 2 N1 4
Subject
表:
SubjectID Title
---------------------------------
1 Computing
2 Maths
3 Economics
4 Physics
5 Geography
Student
表:
UserID Forname Surname SchlYear InOrOut Block1 Block2 Block3 Block4 Pword
----------------------------------------------------------------------------------
1 Jake Richardson 13 1 2 1 NULL 3 password
2 Russell Penn 13 1 5 1 NULL 2 russpass
3 Xander Sheppard 13 1 2 1 4 NULL xander
4 Dan Bostock 13 1 2 1 4 NULL pass
这些表通过以下方式相互链接:
Lesson
表格 - > Subject
表通过SubjectID
作为外键Subject
表格 - > Student
表格Block1
,Block2
,Block3
和Block4
,其中SubjectID
为外键,每个块与a有关主题为每个学生提供最多4个可能的科目我的目的是查询表格,以便在查询运行一天和期间值时找到一个奇异值,并输入个人userID
,从而找到当天个人的课程和期间。
我目前的查询如下,如果试图找到例如Jake Richardson在星期二第1期的课程:
SELECT
lesson.SubjectID
FROM
lesson_tbl AS lesson
LEFT OUTER JOIN
student_tbl AS subject1 ON lesson.SubjectID = subject1.Block1
LEFT OUTER JOIN
student_tbl AS subject2 ON lesson.SubjectID = subject2.Block2
LEFT OUTER JOIN
student_tbl AS subject3 ON lesson.SubjectID = subject3.Block3
LEFT OUTER JOIN
student_tbl AS subject4 ON lesson.SubjectID = subject4.Block4
WHERE
lesson.DayOfWk = 'Mon'
AND lesson.PeriodValue = '5'
AND ((subject1.UserID = '1' AND lesson.blockLessonIsIn = '1') OR
(subject2.UserID = '1' AND lesson.blockLessonIsIn = '2') OR
(subject3.UserID = '1' AND lesson.blockLessonIsIn = '3') OR
(subject4.UserID = '1' AND lesson.blockLessonIsIn = '4'));
这将成功返回值2,即数学。
但是,例如,如果我们在周二第1期搜索Russell Penn的价值:
SELECT
lesson.SubjectID
FROM
lesson_tbl AS lesson
LEFT OUTER JOIN
student_tbl AS subject1 ON lesson.SubjectID = subject1.Block1
LEFT OUTER JOIN
student_tbl AS subject2 ON lesson.SubjectID = subject2.Block2
LEFT OUTER JOIN
student_tbl AS subject3 ON lesson.SubjectID = subject3.Block3
LEFT OUTER JOIN
student_tbl AS subject4 ON lesson.SubjectID = subject4.Block4
WHERE
lesson.DayOfWk = 'Tue'
AND lesson.PeriodValue = '1'
AND ((subject1.UserID = '2' AND lesson.blockLessonIsIn = '1') OR
(subject2.UserID = '2' AND lesson.blockLessonIsIn = '2') OR
(subject3.UserID = '2' AND lesson.blockLessonIsIn = '3') OR
(subject4.UserID = '2' AND lesson.blockLessonIsIn = '4'));
然后返回值是3个2的值,即3个数学值,而它应该只返回1个数学值,因为在我添加的阻塞约束中,在周二的第2个周期只有1个数学值。
我知道数学跨越块1和块4,但这是一个想法,而blockLessonIsIn旨在纠正这样一个事实:它应该只选择与数学所在的特定块相关的课程。
我的数据库设计是否存在严重错误,或者是我愚蠢地错过的明显错误。数据库将被模拟到我的程序中,该程序已经被创建以传递诸如DayOfWk和PeriodValue之类的值,所以这只是阻止我的唯一因素,但它让我完全不知道选择了3个数学值的位置。
请注意,时间表中不需要列,因此如果没有引用它们(即课程表中的Room),请忽略它们。
如果您对我的计划或我可能忘记提及的任何问题有任何疑问,或者需要我更详细地了解我想要通过某些代码行实现的目标,请问这是主要的在我的计划中遇到绊脚石。
感谢你们任何人提供的任何帮助!
答案 0 :(得分:1)
我认为您的课程表中可能有一些数据损坏。在阅读了您的问题以及您希望能够做什么之后,我认为课程中的每个(日,期)对都应该是唯一的,这似乎是合理的。例如,如果学生在周三的第1期,那么我们应该能够肯定地说他是在数学。然而,这似乎并非如此。如果我们运行以下查询,
select dayofwk, periodValue, COUNT(*)
from lesson_tbl
group by dayofwk, periodValue
having COUNT(*) > 1
我们得到以下结果
+ ------- + ----------- + ----- +
| dayofwk | periodValue | count |
+ ------- + ----------- + ----- +
| thu | 1 | 2 |
| tue | 1 | 2 |
| wed | 1 | 2 |
| thu | 3 | 2 |
| fri | 4 | 2 |
+ ------- + ----------- + ----- +
告诉我们这些(日期,期间)组合不是唯一的。如果学生在周三第1期,那么我们无法确定他是否在数学或经济学。
从这里做什么
(1)如果您不相信课程表中的(日,期)组合应该是唯一的,那么您想要的是不可能的。你将无法找到一个奇异的价值"对于(用户,日期,期间)。
(2)如果您认为课程表中的(日,期)组合必须是唯一的,请修复损坏的数据。然后构建以下查询
declare @dayQuery varchar(3) = 'tue'
declare @PeriodQuery int = 1
declare @userQuery int = 1
select *
from lesson_tbl L
inner join student_tbl U
on case L.blockLessonIsIn when 1 then U.Block1
when 2 then U.Block2
when 3 then U.Block3
when 4 then U.Block4
end = L.subjectID
where L.dayofwk = @dayQuery
and L.periodValue = @PeriodQuery
and U.userID = @userQuery