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

如何在关系数据库表上将SQL转换为关系代数,sql,sql-server-2008,relational-database,relational-algebra,Sql,Sql Server 2008,Relational Database,Relational Algebra,共有三个表格:学生、课程和成绩 sid、cid和sid-cid(超级键)是每个表的主键 学生: sid sname address ----------------- S1 Adam Abawama S2 Mery Ignora S3 Aisha Icterra S4 Sello Icterra S5 Mery Kaysers 课程: cid cname dept ------------------ C1 Db Ceng C2 Prog Ceng

共有三个表格:
学生
课程
成绩

sid
cid
sid-cid
(超级键)是每个表的主键

学生

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

cid cname    dept
------------------
C1  Db       Ceng
C2  Prog     Ceng
C3  Calculus Math
C4  Stat     EE
C5  Alg      Ceng
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
等级

cid cname    dept
------------------
C1  Db       Ceng
C2  Prog     Ceng
C3  Calculus Math
C4  Stat     EE
C5  Alg      Ceng
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
问题

  • 列出参加过
    ceng
    EE
    课程的学生姓名

  • 查找从课程
    数据库中获得最高分数的学生的
    sid

  • 第一季度我的SQl答案

    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是返回错误的结果,如何修复它?
    如何为这些命令编写关系代数?

    要深入了解,您可以阅读作者提供的“数据库系统概念”或免费幻灯片

    使用以下命令:

    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';
    

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

    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')
    

    请参阅:

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

    第一步 您需要以某种形状或形式进行自连接。此查询列出了在EE课程中取得成绩的学生(按sid分类):

    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的学生,并将其与学生表格连接起来,列出他们的姓名:

    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放在主查询选择列表中。

    结果必须是;S1和S4,但结果集是错误的。哦,我没有注意到“两者”,好的,我会相应地编辑我的答案。呵呵,也许我们可以更正为s.sid写入s.sname。选择s.sid。。。因为我们需要名字:)@DjMix-当然你应该,我这样做了,因为我想给你看S1和S4。另外,我从第二季度的SQL答案中得到了双倍的结果,我必须写不同的关键字吗?@DjMix-对于第二季度,是的,你需要
    不同的
    ,因为
    成绩
    每门课程都有一个相同的学生ID。如果学生在每门课程中都得到相同的分数,那么你会看到该学生的ID在每门课程中出现一次!