【问题标题】:SQL Server alternative to using subquery in aggregate functionSQL Server 替代在聚合函数中使用子查询
【发布时间】:2018-12-03 07:24:31
【问题描述】:

我正在使用聚合函数来计算特定学生的 GPA。我有三个表:COURSE、SECTION 和 ENROLL。这些表是这样创建的:

create table COURSE
(
    Cno     varchar(9) primary key, 
    Cname   varchar(50),
    Credit  int check (Credit > 0)
);

create table SECTION
(
    Cno     varchar(9) REFERENCES COURSE(cno),
    Sno     varchar(9),
    Semester    varchar(15) check(Semester in('Fall','Spring','Summer')), 
    Year    int, 
    Sid     varchar(9) primary key 
);

create table ENROLL
(
    Mno     varchar(9) REFERENCES STUDENT(Mno),
    Sid     varchar(9) REFERENCES SECTION(Sid),
    Grade   CHAR check(Grade in('A','B','C','D','F')),
    primary key(Mno,Sid)
);

我必须将 ENROLL 表中的 char Grade 转换为浮点值。在我的情况下计算 GPA 的方法是:

SUM(grade of each course*credit hours of the course)/SUM(credit hours of each course)

这是我目前尝试计算 GPA 的方式:

 @grade =     
(
 (select SUM(CASE 
              WHEN Grade = 'A' THEN 4.0
              WHEN Grade = 'B' THEN 3.0
              WHEN Grade = 'C' THEN 2.0
              WHEN Grade = 'D' THEN 1.0
              WHEN Grade = 'F' THEN 0.0
             END
             * (
                select c.Credit from COURSE c where c.Cno = (
                 select s.Cno from SECTION s where s.Sid in (
                  select Sid from ENROLL where Mno = @mNum
                 )
                )
             )
         ) FROM ENROLL 
         where Mno = @mNum 
 ) / (
  select SUM(Credit) from COURSE c where c.Cno = (
   select s.Cno from SECTION s where s.Sid in (
    select Sid from ENROLL where Mno = @mNum
   )
  ) group by c.Cno
 )
)

然而,有一个明显的问题。聚合函数中不能有子查询,所以我很难找到替代方法。任何帮助将不胜感激。

【问题讨论】:

  • 您使用的是哪个DBMS 产品? “SQL”只是一种查询语言,而不是特定数据库产品的名称。请为您正在使用的数据库产品添加tag postgresql, oracle, sql-server, db2, ...
  • 哪个表包含学时?
  • 对不起,我漏掉了!我正在使用 SQL Server 并编辑了帖子以反映这一点。
  • COURSE 包含学分。这是Credit 列名
  • 使用join代替子查询..

标签: sql sql-server group-by aggregate-functions


【解决方案1】:

看来你只需要把三个表一起JOIN:

SELECT ENROLL.Mno, SUM(CASE
    WHEN Grade = 'A' THEN 4.0
    WHEN Grade = 'B' THEN 3.0
    WHEN Grade = 'C' THEN 2.0
    WHEN Grade = 'D' THEN 1.0
    WHEN Grade = 'F' THEN 0.0
END * COURSE.Credit) / SUM(COURSE.Credit)
FROM ENROLL
INNER JOIN SECTION ON ENROLL.Sid = Section.Sid
INNER JOIN COURSE ON SECTION.Cno = COURSE.Cno
GROUP BY ENROLL.Mno

【讨论】:

  • 您好,如果您能帮我解决另一个问题,我将不胜感激。我正在运行一个使用局部变量 @grade 的更新语句,它是上述 GPA 的结果,但是它说 @grade 包含多个值。你知道是什么原因造成的吗?谢谢。
  • 如果您要为一个特定学生 (Mno) 计算 @grade,则从选择中删除 ENROLL.Mno,完全删除 group by 并添加 WHERE ENROLL.Mno = @Mno
  • 非常感谢您的帮助!我更新了我的代码以反映您的所有更改;起初我没有认出其中一些。现在可以了!谢谢!
【解决方案2】:

我会尝试先加入 TABLES ENROLL 和 SECTION。

这将为我提供与 Mno 相关的所有部分。

之后我将加入 COURSE 表以获取与 Mno 关联的所有课程。

选择 * 从报名 加入b部分 a.Sid=b.Sid 加入课程 c 关于 b.Cno=c.Cno

然后我将按 a.Mno 分组。这意味着我正在根据定义的计算计算每个 Mno 的 GPA。

**SUM(grade of each course*credit hours of the course)/SUM(credit hours of each course)**

select a.Mno
       ,sum(case WHEN c.Grade = 'A' THEN 4.0
                 WHEN c.Grade = 'B' THEN 3.0
                 WHEN c.Grade = 'C' THEN 2.0
                 WHEN c.Grade = 'D' THEN 1.0
                 WHEN c.Grade = 'F' THEN 0.0
             END * c.Credit)/sum(c.credit) 
  from enroll a
  join section b
    on a.Sid=b.Sid
  join course c
    on b.Cno=c.Cno
group by a.Mno 

【讨论】:

  • 您好,如果您能帮我解决另一个问题,我将不胜感激。我正在运行一个使用局部变量 @grade 的更新语句,它是上述 GPA 的结果,但是它说 @grade 包含多个值。你知道是什么原因造成的吗?谢谢。
  • 没关系,我更新了我的代码以完全反映您的更改,它使它工作。非常感谢您的帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-05
  • 2013-04-25
  • 2011-09-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多