选择完全满足给定先决条件列表的课程

时间:2013-12-19 00:58:06

标签: mysql sql prerequisites relational-division

我正在尝试编写一个SQL查询,该查询将返回一个人符合条件的课程列表,给出已完成主题的列表(用作先决条件)。

我的数据库是这样布局的。

   Prerequisite:
   +---------------+---------------+
   |      Id       |     Name      |         (Junction table)
   |---------------|---------------|         CoursePrerequisites:
   |      1        |   Maths       |         +---------------+---------------+
   |      2        |   English     |         |  Course_FK    | Prerequisite_FK
   |      3        |   Art         |         |---------------|---------------|
   |      4        |   Physics     |         |      1        |      1        |
   |      5        |   Psychology  |         |      1        |      2        |
   +-------------------------------+         |      2        |      3        |
                                             |      2        |      5        |
   Course:                                   |      5        |      4        |
   +---------------+---------------+         +---------------v---------------+
   |      Id       |     Name      |
   |---------------|---------------|
   |      1        |   Course1     |
   |      2        |   Course2     |
   |      3        |   Course3     |
   |      4        |   Course4     |
   |      5        |   Course5     |
   +---------------v---------------+

我一直在尝试一个看起来像这样的查询:

    SELECT  DISTINCT C.*
        FROM    Course C
    INNER JOIN JNCT_Course_Prerequisites cp
        ON C.Id = cp.Course_FK
    WHERE   cp.Prerequisite_FK IN (SELECT Prerequisites.Id FROM Prerequisites Where Name = 'Art' AND Name = etc etc)

然而,这将返回Art是先决条件的任何课程,而不仅仅是给定的先决条件列表完全满足的课程。例如。它将返回课程2,只考虑艺术作为学生的先决条件,即使课程也需要心理学。

我对SQL很新,所以如果我的表格布局有问题或者这是一个看似简单的问题,请原谅。我一直在尽我所能地搜索,但只能找到解决这个问题的反面的解决方案。

似乎我需要对集​​合进行区分:

  • 构建一组具有先决条件的课程(针对每个先决条件?)
  • 构建一组没有先决条件的课程
  • 执行集合操作的差异:选择第一组中的全部存在而不存在第二组 看起来很简单,但我现在对联结表以及如何在许多先决条件中处理这个问题感到困惑。

我希望返回至少完全满足给定先决条件列表的行,而不是至少包含其中一个先决条件的行。

例如,如果给出先决条件'艺术','英语','心理学',则应该返回的唯一行是Course2(先决条件超过满意)。

由于

3 个答案:

答案 0 :(得分:1)

SELECT  * FROM Course C LEFT JOIN Course_Prerequisites cp ON C.Id = cp.Course_FK 
         WHERE Prerequisite_FK IN (SELECT Prerequisites.Id FROM Prerequisites Where Name = 'Art' OR Name = etc etc)
 NOT EXISTS   
   (SELECT  * FROM Course C LEFT JOIN Course_Prerequisites cp ON C.Id = cp.Course_FK 
         WHERE Prerequisite_FK NOT IN (SELECT Prerequisites.Id FROM Prerequisites Where Name = 'Art' OR Name = etc etc))

答案 1 :(得分:0)

我能够通过以下查询解决问题(并且在此过程中还学习了一些关于GROUP_CONCAT的内容)。实际上并不需要GROUP_CONCAT,但会使输出更清晰。这也取决于 在'GROUP BY Course.id' - 如果不需要,可以删除这些。此解决方案执行必要的集合差异,并仅选择至少满足先决条件的课程。

我还是很陌生,所以如果有什么可以做得更好的话,请告诉我。

SELECT Course.id, course.Name, GROUP_CONCAT(DISTINCT Prerequisite.Name) AS 'Prerequisite Name(s)'
FROM Course
  LEFT JOIN CoursePrerequisites ON Course.id = CoursePrerequisites.Course_FK
  LEFT JOIN Prerequisite ON Prerequisite.id = CoursePrerequisites.Prerequisite_FK 
WHERE NOT EXISTS 
  (SELECT 1
    FROM CoursePrerequisites 
    WHERE Course.id = CoursePrerequisites.Course_FK
      AND CoursePrerequisites.Prerequisite_FK NOT IN (SELECT Prerequisite.id FROM Prerequisite Where Name = 'Art' OR Name = 'English' OR Name = 'Psychology''))
GROUP BY Course.id;

答案 2 :(得分:0)

1,     SELECT Course_FK,COUNT(1)AS Num FROM CoursePrerequisites GROUP BY Course_FK

并将结果存储在临时表temp_a中。

2,SELECT Course_FK,COUNT(1)AS Num FROM CoursePrerequisites a INNER JOIN先决条件b ON a.Prerequisite_FK = b.Id GROUP BY Course_FK

并将结果存储在临时表temp_b中。

3,选择a.Course_FK FROM temp_a a INNER JOIN temp_b b ON a.Course_FK = b.Course_FK AND a.Num = b.Num

这将是合格课程的ID