我有一个查询,它给了我想要的结果,但需要永远执行。任何人都可以给我任何建议来加快这个问题吗?
以下是查询:
SELECT StudentDB.studentid,
ClassDB.classID,
ClassDB.class_level,
ClassDB.class_title,
ClassDB.TIME,
ClassDB.teacher,
StudentDB.first_name,
StudentDB.last_name
FROM StudentDB
INNER JOIN AttendanceDB
ON StudentDB.studentid = AttendanceDB.studentid
INNER JOIN ClassDB
ON AttendanceDB.classid = ClassDB.classID
WHERE StudentDB.studentid NOT IN (
SELECT studentID
FROM AttendanceDB
WHERE (
class_time >= '$todaysdate1'
AND class_time < '$tomorrowsdate1'
)
AND (
furikae = '0'
OR furikae = '2'
OR furikae = '1'
)
)
AND DATE (AttendanceDB.class_time) = '$datecheck'
AND AttendanceDB.furikae = '3'
UNION ALL
SELECT StudentDB.studentid,
ClassDB.classID,
ClassDB.class_level,
ClassDB.class_title,
ClassDB.TIME,
ClassDB.teacher,
StudentDB.first_name,
StudentDB.last_name
FROM StudentDB
INNER JOIN RegDB
ON StudentDB.studentID = RegDB.studentid
INNER JOIN ClassDB
ON ClassDB.classID = RegDB.classid
WHERE StudentDB.studentid NOT IN (
SELECT studentID
FROM AttendanceDB
WHERE (
class_time >= '$todaysdate1'
AND class_time < '$tomorrowsdate1'
)
AND (
furikae = '0'
OR furikae = '2'
OR furikae = '1'
)
)
AND ClassDB.day = '$dayofweek'
ORDER BY TIME ASC,
class_title ASC
基本上我的数据库结构是这样的:
StudentDB
ClassDB
RegDB
AttendanceDB
StudentDB(这个有很多专栏的数据,如学生和电话号码不相关,我会删除以缩写)
studentid int(11) No None AUTO_INCREMENT
first_name text latin1_swedish_ci No None
last_name text latin1_swedish_ci No None
class_level text latin1_swedish_ci No None
ClassDB
classID int(11) No None AUTO_INCREMENT
class_title text latin1_swedish_ci No None
class_level text latin1_swedish_ci No None
day text latin1_swedish_ci No None
time time No None
teacher text latin1_swedish_ci No None
RegDB
regid int(11) No None AUTO_INCREMENT
classid int(11) No None
studentid int(11) No None
AttendanceDB
attendanceID int(11) No None AUTO_INCREMENT
studentid int(11) No None
classid int(11) No None
class_time timestamp on update CURRENT_TIMESTAMP No CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
furikae int(11) No None
RegDB将StudentDB链接到ClassDB,该学生参加哪个班级。 AttendanceDB记录哪个学生实际上参加哪个班级,以及记录学生将加入(将来)一个不属于他们常规班级的班级。
我想用这个SELECT做的是让所有注册到班级或有不正常约会的学生,减去那些已经被标记为当天登记的学生。
正如我所说,这会输出正确的结果,但速度极慢。
答案 0 :(得分:1)
让我们将union的第一部分称为query1,将union的第二部分称为query2。现在在query1中,AttendenceDB是中间表b / n studentDB和ClassDB,在query2中,RegDB是中间表b / n studentDB和ClassDB。和其他条件相同。如果我们首先联合RegDB和AttendenceDB的秒数,然后将这个结果与studentDB和ClassDB结合起来,我们可以避免不必要的加入。
答案 1 :(得分:1)
更多详细问题我稍后可以使用解决方案进行编辑。为了更好地理解您的数据结构,请让我为自己(以及其他任何人)澄清以下内容。
StudentDB - 很明显。每个学生一个记录。
ClassDB - 提供的所有可能类的列表,并且可以具有相同类的多个实例,例如编程101,但可以在不同日期,不同学期,教授特定实例等提供。 / p>
RegDB - 列出学生注册特定课程的所有条目。因此,对于学生来说,每个记录都是1:1。
AttendanceDB - 每位学生的出勤率:上课时间:日期。我会认为考勤表也有出勤的班级ID。如果一个学生有5个班级,他们可能会出现在1-3班,并提前离开4-5班。如果这是公立学校K-12,并且一名学生提前离开参加博士约会,你知道他们在那里参加一些课程,但不是全部。如果大学同样地,不能保证他们在某一天有多个班级,但可以参加一个班级,但不一定是所有班级。
因此,我会以这种方式看待它。首先,给我所有符合相关日期的课程(ClassDB)。然后到注册表中注册谁,然后注册到学生。那些永远是有效的JOIN。由此,基于细微差别/状态
的条件加入到考勤表如果WOULD有助于查看表的结构,即使缩写为确认查询关联/需要的列。我希望班级表格具有可能适用的日期范围......例如2015年9月1日至2015年12月18日的课程。
因此我的TEMPORARY解决方案。我添加了Furikae字段,因此您可以获得ALL并将结果视为此查询的基线考虑因素。
SELECT
S.studentid,
C.classID,
C.class_level,
C.class_title,
C.TIME,
C.teacher,
S.first_name,
S.last_name,
ADB.furikae
FROM
ClassDB C
JOIN RegDB R
on C.ClassID = R.ClassID
JOIN StudentDB S
ON R.studentid = S.studentID
LEFT JOIN AttendanceDB ADB
on C.ClassID = ADB.ClassID
AND S.StudentID = ADB.StudentID
AND ADB.class_time >= '$todaysdate1'
AND ADB.class_time < '$tomorrowsdate1'
WHERE
'$datecheck' BETWEEN C.StartDate and C.EndDate
AND C.day = '$dayofweek'
AND ( ADB.Furikae IS NULL
OR ADB.Furikae = '3' )
现在,您所要做的就是根据Furikae字段应用额外的AND子句。我提出了这样一个标准的例子,因为我不知道这个Furikae状态字段的目的。此外,出勤的确认是专门查找当前日期基础,因为学生可能在一周前参加,但不是基于“今天”参加。
对于索引,我建议如下。同样,不知道班级表是否具有从/到日期考虑
table indexed on
ClassDB (classID, StartDate, EndDate )
RegDB (classID, StudentID )
StudentDB (StudentID) -- would expect as it is primary key
AttendanceDB (classID, StudentID, class_time, Furikae )