背景
我遇到了以下问题,涉及三个表
class_sectors
表包含三类类
classes
表包含学生可以参加的课程列表
class_choices
包含每个部门的学生的第一,第二和第三课程选择。因此对于扇区1,Student_A将class_1作为第一选择,class_3作为第二选择,class_10作为第三选择,然后对于扇区2,他有另外三个选择,等等......
class_choices
表包含以下列:
kp_choice_id | kf_personID | kf_sectorID | kf_classID | preference | assigned
我认为列名是不言自明的。 preference
是1,2或3.一旦我们审核了学生的选择并将其分配到班级,assigned
就是布尔值设置为1。
问题:
编写一个sql查询,告诉学生他们为每个扇区分配了哪个类。如果尚未分配他们的课程,则应默认显示他们的第一个偏好。
我实际上有这个工作,但使用两个(非常臃肿?)sql查询如下:
$choices = $db -> Q("SELECT
*, concat_ws(':', `kf_personID`, `kf_sectorID`) AS `concatids`
FROM
`class_choices`
WHERE
(`assigned` = '1')
GROUP BY
`concatids`
ORDER BY
`kf_personIDID` ASC,
`kf_sectorID` ASC;");
$choices2 = $db -> Q("SELECT
*, concat_ws(':', `kf_personID`, `kf_sectorID`) AS `concatids`
FROM
`class_choices`
WHERE
`preference` = '1'
GROUP BY
`concatids`
HAVING
`concatids` NOT IN (".iimplode($choices).")
ORDER BY
`kf_personID` ASC,
`kf_sectorID` ASC;");
if(is_array($choices2)){
$choices = array_merge($choices,$choices2);
}
现在$choices
确实有我想要的东西。
但我确信有一种方法可以简化这一点,合并两个SQL查询,因此它更轻量级。
是否有某种条件SQL查询可以执行此操作???
答案 0 :(得分:1)
您的解决方案使用两个步骤来根据需要过滤数据。由于您正在生成报告,这是一个非常好的方法,即使它看起来比您想要的更冗长。
这种方法的优点是调试和维护更容易,这是一个很大的优势。
要改善这种情况,您需要考虑数据结构本身。当我查看class_choices
表时,会看到以下字段:kf_classID, preference, assigned
,其中包含关键信息。
对于每个班级,assigned
字段为0(默认)或1(当为学生分配班级偏好时)。默认情况下,preference = 1
的课程是指定的课程,因为您在assigned=0
的报告中将其显示在特定部门中所有学生的课程选择中。
可以通过强制执行以下业务规则来改进数据模型:
对于preference=1
,请设置默认值assigned=1
。当班级选择过程
发生,如果学生被分配了第二或第三选择,则首选项1未分配,并指定备用选项。
这意味着应用程序中的代码更多一些,但它使报告更容易。
难点的来源是分配过程没有明确指定第一个偏好。如果学生无法获得第一选择,它只会更新assigned
。
总之,您的SQL很好,而改进来自于再次查看数据模型。
希望这会有所帮助,祝你工作顺利!