两个表连接和组合麻烦

时间:2018-02-22 02:03:28

标签: sql database oracle

使用Oracle SQL开发人员和我目前正在尝试解决此问题:
提供一个按字母顺序排列的学生名单(学生姓氏后跟名字),他们的总体平均成绩为93或更高。名称应该是一列,姓氏首先排序,然后按姓氏排序,然后是名字。

这是我的查询,它返回:"不是Group By表达式"

SELECT Student.Last_Name || ', ' || Student.First_Name AS "Student Name"
FROM Student, Grade
WHERE Student.Student_Id = Grade.Student_Id
GROUP BY Grade.Student_Id
HAVING AVG(Grade.Numeric_Grade) > 92
ORDER BY Last_Name;

我有点困惑使用分组和两个表加入,我希望一些更有经验的眼睛可以看一看。谢谢你的时间。

2 个答案:

答案 0 :(得分:1)

首先,学会使用正确的,明确的JOIN语法。其次,SELECT中的未聚合列需要与GROUP BY列匹配。第三,使用表别名:

SELECT s.Last_Name || ', ' || s.First_Name AS "Student Name"
FROM Student s JOIN
     Grade g
     ON s.Student_Id = g.Student_Id
GROUP BY s.Last_Name || ', ' || s.First_Name
HAVING AVG(g.Numeric_Grade) > 92
ORDER BY s.Last_Name || ', ' || s.First_Name;

如果两名学生的姓名相同,您可能还想在s.Student_Id中加入GROUP BY

答案 1 :(得分:0)

  1. 无需使用INNER JOIN语法。我更喜欢 与关系代数符号相关的经典语法 这看起来更自然。

  2. 在select-list和having列表中只能有表达式的表达式或表达式的聚合函数。

  3. 您应该仔细检查您构建的组是否是您想要的组。如果您按s.Last_Name || ', ' || s.First_Name分组 两个同一First_NameLast_Name的学生之间没有区别 StudentId。这是没有意义的。使用表的主键 分组。

  4. 如果您愿意,可以使用选择列表中表达式的订单号来简化order by子句

  5. 请务必仔细检查内部联接是否合适或是否需要外部联接。

  6. 所以请按列表中的FirstName使用。

    由于技术原因,也将LastNameSELECT Student.Last_Name || ', ' || Student.First_Name AS "Student Name" FROM Student, Grade WHERE Student.Student_Id = Grade.Student_Id GROUP BY Student.Student_Id, Student.Last_Name, Student.First_Name HAVING AVG(Grade.Numeric_Grade) > 92 ORDER BY 1, Student.Student_Id 添加到分组依据中:

    SELECT 
        Student.Last_Name || ', ' || Student.First_Name AS "Student Name"
    FROM 
        Student, 
        Grade
    WHERE 
        Student.Student_Id = Grade.Student_Id
    GROUP BY 
        Student.Student_Id, 
        Student.Last_Name || ', ' || Student.First_Name
    HAVING 
        AVG(Grade.Numeric_Grade) > 92
    ORDER BY 
        1, 
        Student.Student_Id
    

    或者也可以在group-by子句

    中使用select-list的表达式
    Student.Last_Name || ', ' || Student.First_Name

    请注意,我们需要group-by子句中的StudentId表达式Student.Last_Name || ', ' || Student.First_Name我们在group by子句中仅出于技术原因。如果我们不这样做,我们就会收到错误。我们可以在group by子句中避免使用这个表达式。 SELECT MAX(Student.Last_Name || ', ' || Student.First_Name) AS "Student Name" FROM Student, Grade WHERE Student.Student_Id = Grade.Student_Id GROUP BY Student.Student_Id, HAVING AVG(Grade.Numeric_Grade) > 92 ORDER BY 1, Student.Student_Id 对于组中的所有元素都是相同的,MAX(或MIN)函数选择其中一个相同的值。

    -- incorrect statement
    SELECT 
        Student.Last_Name || ', ' || Student.First_Name AS "Student Name"
    FROM 
        Student, 
        Grade
    WHERE 
        Student.Student_Id = Grade.Student_Id
    GROUP BY 
        Student.Student_Id, 
        Student.Last_Name || ', ' || Student.First_Name
    HAVING 
        count(*) <=3
    ORDER BY 
        1, 
        Student.Student_Id
    

    如果你想选择所有不超过3年级的学生,那么内部联接是错误的:

    SELECT 
        Student.Last_Name || ', ' || Student.First_Name AS "Student Name"
    FROM 
        Student 
        LEFT OUTER JOIN Grade
            ON Student.Student_Id = Grade.Student_Id
    GROUP BY 
        Student.Student_Id, 
        Student.Last_Name || ', ' || Student.First_Name
    HAVING 
        count(*) <=3
    ORDER BY 
        1, 
        Student.Student_Id
    

    这里你必须使用外连接。否则,将不会显示0年级的学生

      private void ShowProgressBar()
            {
                DialogProgress dialogProgress = new DialogProgress("ATAM Desktop", "Loading module...");
                dialogProgress.Show();
            }
    
    
    
     thread.SetApartmentState(ApartmentState.STA);
     thread.Start();
    

    同样重要的是在group-by-clause中使用主键。