查询包括TOP和AVG

时间:2015-06-20 17:46:41

标签: sql sql-server average

这是我在申请中必须处理的最后一个问题,我希望有人会帮助,因为我很无能,我做了我的研究,找不到合适的解决方案。

我有一个'大学管理'申请。我需要制作包含少量表格的报告。

问题出在SQL Query中我必须完成。查询需要列出最佳学生名单,学生“最佳”的条件是等级平均。

我有3列(students.stID& examines.grades)。我需要得到我的'examines.grades'列的平均值,将表格从最高(平均成绩)排序到最低,我需要过滤'n'最佳'平均值'。

用户可以输入过滤器编号,正如我所说,应用程序需要显示“n”个最佳平均值。

问题在于我的SQL知识(不是mySQL文学而是T-SQL)。这就是我对我的SQL查询的看法,但问题在于“SELECT TOP”,因为当我按下我的按钮时,应用程序仅从所选的TOP'n'行取平均值。

SELECT TOP(@topParam) student.ID, AVG(examines.grades)
FROM            examines INNER JOIN
                         student ON examines.stID = student.stID
WHERE        (examines.grades > 1)

例如:

StudentID  Grade
1          2
2          5
1          5
2          2
2          4
2          2

EXIT:

StudentID  Grade_Average
1          3.5
2          3.25

3 个答案:

答案 0 :(得分:1)

对于每个{{1>,您应该使用group by子句来计算平均成绩(如果examines.grades具有整数类型,则应cast为浮点类型) }和student.ID子句将输出限制为仅order by n 最高平均成绩:

top

答案 1 :(得分:1)

不耐烦,我认为这就是你要找的东西。您没有指定您正在使用的SQL Server版本。

DECLARE @topParam INT = 3;      -- Default

DECLARE @student TABLE (StudentID INT);     -- Just for testing purpose
DECLARE @examines TABLE (StudentID INT, Grades INT);

INSERT INTO @student (StudentID) VALUES (1), (2);

INSERT INTO @examines (StudentID, Grades)
VALUES (1, 2), (2, 5), (1, 5), (2, 2), (2, 4), (2, 2);

SELECT DISTINCT TOP(@topParam) s.StudentID, AVG(CAST(e.grades AS FLOAT)) OVER (PARTITION BY s.StudentID) AS AvgGrade
FROM @examines AS e
INNER JOIN @student AS s
    ON e.StudentID = s.StudentID
WHERE e.grades > 1
ORDER BY AvgGrade DESC;

如果您提供一些基本数据,我会根据您的需求调整查询。

结果:

StudentID   AvgGrade
--------------------
1           3.500000
2           3.250000

快速解释:

查询在派生表中查找平均成绩,然后查询它按其排序。另一个提示:如果有多名学生可以申请第三名,你可以在WITH TIES条款中使用TOP选项来吸引更多学生。

如果您想按照我在评论中的建议制作程序,请使用以下代码段:

CREATE PROCEDURE dbo.GetTopStudents
(
    @topParam INT = 3
)
AS
BEGIN
    BEGIN TRY    
        SELECT DISTINCT TOP(@topParam) s.StudentID, AVG(CAST(e.grades AS FLOAT)) OVER (PARTITION BY s.StudentID) AS AvgGrade
        FROM examines AS e
        INNER JOIN student AS s
            ON e.StudentID = s.StudentID
        WHERE e.grades > 1
        ORDER BY AvgGrade DESC;
    END TRY
    BEGIN CATCH
        SELECT ERROR_NUMBER(), ERROR_MESSAGE();
    END CATCH
END

后来就这样称呼它。这是封装逻辑的好方法。

EXEC dbo.GetTopStudents @topParam = 3;

答案 2 :(得分:0)

不需要返回重复行的A Windowed Aggregate,然后您需要DISTINCT再次删除它们。这是一个简单的聚合,你的原始查询已经非常接近了:

SELECT TOP(@topParam) student.ID, AVG(CAST(grade AS FLOAT)) as AvgGrade
FROM            examines INNER JOIN
                         student ON examines.stID = student.stID
WHERE        (examines.grades > 1)
group by student.ID
order by AvgGrade DESC