如何在关系数据库表上将SQL转换为关系代数

时间:2014-03-30 09:12:40

标签: sql sql-server-2008 relational-database relational-algebra

共有3个表:StudentsCoursesGrades

sidcidsid-cid(超级密钥)是每个表的主键。

Students

sid sname address
-----------------
S1  Adam  Abawama
S2  Mery  Ignora
S3  Aisha Icterra
S4  Sello Icterra
S5  Mery  Kaysers

Courses

cid cname    dept
------------------
C1  Db       Ceng
C2  Prog     Ceng
C3  Calculus Math
C4  Stat     EE
C5  Alg      Ceng

Grades

sid cid grade
--------------
S1  C1  50
S1  C2  85
S1  C3  60
S1  C4  90
S1  C5  50
S2  C1  30
S2  C2  40
S3  C2  85
S4  C2  80
S4  C4  75
S4  C5  60

问题

  1. 列出同时参加cengEE课程的学生的姓名

  2. 在课程sid

  3. 中找到获得最高成绩的学生database

    我的SQl回答Q1

    SELECT s.sname
    FROM Students s
    JOIN Grades g ON s.sid = g.sid
    JOIN Courses c ON g.sid = c.sid
    AND c.dept IN ("Ceng","EE")
    

    我对第二季的SQL答案

    SELECT sid
    FROM Grades
    WHERE grade =
        (SELECT max(grade)
         FROM Grades
         GROUP BY cid HAVING Grades.cid = "C1")
    

    答案1是返回错误的结果,如何解决? 我怎样才能为这些命令编写关系代数?

3 个答案:

答案 0 :(得分:1)

要获得一些见解,您可以阅读"数据库系统概念"或者作者提供的this免费幻灯片。

使用此:

SELECT s.sname
FROM Students s
JOIN Grades g ON s.sid = g.sid
JOIN Courses c ON g.cid = c.cid
WHERE c.dept = 'Ceng'
INTERSECT 
SELECT s.sid
FROM Students s
JOIN Grades g ON s.sid = g.sid
JOIN Courses c ON g.cid = c.cid
WHERE c.dept = 'EE';

答案 1 :(得分:1)

另一种方法是使用两个相关的子查询,如下所示:

select S.SNAME
from STUDENTS S
where exists (select G1.SID
              from GRADES G1 inner join COURSES C1 on G1.CID=C1.CID
              where G1.SID = S.SID
                and C1.DEPT = 'Ceng')
  and exists (select G2.SID
              from GRADES G2 inner join COURSES C2 on G2.CID=C2.CID
              where G2.SID = S.SID
                and C2.DEPT = 'EE')

请参阅:http://sqlfiddle.com/#!3/2fd72/4

答案 2 :(得分:0)

我喜欢使用TDQD - 测试驱动的查询设计。您分阶段构建查询,验证每个阶段。这是一个相当简单的查询 - 它只需要两个步骤(尽管可以说我已经将两个步骤压缩到第2步)。

第1步

您需要以某种形式或形式进行自我加入。此查询列出了学生(sid)在EE课程中的成绩:

SELECT g.sid
  FROM Grades  AS g
  JOIN Courses AS c ON g.cid = c.cid AND c.dept = "EE"

第2步

您可以将步骤1中的查询用作一个子查询和类似的子查询,用于" Ceng"生成两个表格'有EE和Ceng的学生名单;你加入这些表格,让那些同时参与EE和Ceng的学生参加,并与Students表一起列出他们的名字:

SELECT s.name
  FROM Students AS s
  JOIN (SELECT DISTINCT g.sid
          FROM Grades  AS g
          JOIN Courses AS c ON g.cid = c.cid AND c.dept = "EE"
       ) AS ee
    ON s.sid = ee.sid
  JOIN (SELECT DISTINCT g.sid
          FROM Grades  AS g
          JOIN Courses AS c ON g.cid = c.cid AND c.dept = "Ceng"
       ) AS ceng
    ON s.sid = ceng.sid

如果学生需要2个EE和1个Ceng课程,DISTINCT资格赛是必要的;它可以防止它们在输出中出现两次。当然,您也可以将DISTINCT放在主查询选择列表中。