Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 如何从组计数中获取最大值_Sql_Sql Server_Tsql_Aggregate Functions - Fatal编程技术网

Sql 如何从组计数中获取最大值

Sql 如何从组计数中获取最大值,sql,sql-server,tsql,aggregate-functions,Sql,Sql Server,Tsql,Aggregate Functions,除了基本的插入和选择,我最近还开始学习tsql,我有一个训练的测试数据库,还有一个查询我不能真正开始工作 该查询中使用了3个表,图中有简化的字段和关系 我有两个问题-第一个是简单地显示学生和每个科目的分数。第二是做我想做的事——向学生展示他们取得的最大分数,所以。 科目1-分数1、5、3、4计数-4 受试者2-分数5,4,5-计数-3 查询显示了4,根据我检查的结果,它返回了正确的结果,但我还需要一件事——只是显示标记最多的主题的名称,所以在示例中是subject1 查询1结果的一部分 查询2和

除了基本的插入和选择,我最近还开始学习tsql,我有一个训练的测试数据库,还有一个查询我不能真正开始工作

该查询中使用了3个表,图中有简化的字段和关系

我有两个问题-第一个是简单地显示学生和每个科目的分数。第二是做我想做的事——向学生展示他们取得的最大分数,所以。 科目1-分数1、5、3、4计数-4 受试者2-分数5,4,5-计数-3 查询显示了4,根据我检查的结果,它返回了正确的结果,但我还需要一件事——只是显示标记最多的主题的名称,所以在示例中是subject1

查询1结果的一部分

查询2和查询3结果的一部分

问题是,当我添加到select语句subject name时,我得到了查询1的结果——没有更多的最高分数,只有学生、科目和每个科目的分数


如果有人能说出我遗漏了什么,我将不胜感激:

这是一个每个学生得分最高的查询,将其放在sql文件/批处理的顶部,它将生成另一个表,您可以连接到其他表以获得学生名和科目名:

WITH studentBest as 
SELECT * FROM(
  SELECT *, ROW_NUMBER() OVER(PARTITION BY studentid ORDER BY mark DESC) rown  
  FROM marks) a 
WHERE rown = 1)
例如,你这样使用它

--the WITH bit goes above this line
SELECT *
FROM
  studentBest sb 
  INNER JOIN
  subject s
  ON sb.subjectid = s.subjectnumber

这也是你应该如何做你的连接

它是如何工作的?好它建立了一个递增计数器,每当studentid更改partition子句并且numberin以des ending mark order和order by子句的形式出现时,该计数器就会重新启动。外部查询仅选择行号为1的行,即每个学生的最高分数

为什么我不能使用分组方式

可以,但是您必须编写一个查询,将分数表汇总为每个学生的最高分数,然后您必须将该数据连接回分数表以检索主题,而所有这些都是非常虚假的,通常效率较低

如果有两个科目的分数相同怎么办

如果您想同时看到这两个行,请使用秩而不是行号

根据您的评论进行编辑:

上述方法的扩展:

SELECT * FROM
(
  SELECT *, ROW_NUMBER() OVER(PARTITION BY su, st ORDER BY c DESC) rn FROM
  (
    SELECT studentid st, subjectid su, count(*) c
    FROM marks
    GROUP BY st, su
  ) a
) b
INNER JOIN student stu  on b.st = stu.studentnumber
INNER JOIN subject sub on b.su = sub.subjectnumber
WHERE
  b.rn = 1
我们按学生/受试者统计分数,然后按每个学生-受试者对计数的降序排列,然后只选择第一行并加入其他需要的数据

好的,多亏了Caius Jard、其他堆栈的一些问题和一些实验,我成功地编写了工作查询,所以我就是这样做的

首先,我从query1创建了视图,并在其中添加了一列-studentId。 然后我写了一个几乎让我满意的问题。这个问题对我完成这项任务帮助很大:

它给出了以下结果

这就是我想要达到的目标,但有一个例外——如果学生在多个科目中的分数相同,它会显示所有科目的分数——这很好,但我决定将这限制在每个学生的第一个成绩上——我不能简单地将前1名放在第一位 所以我使用了Caius Jard展示的类似解决方案——行数和窗口函数——它让我有机会选择行数等于1的记录。 我根据这个查询创建了另一个视图,我可以简单地编写最后一个视图

SELECT marks.Surname, marks.SubjectName, marks.Marks_count
FROM StudentsMaxMarksAmount marks
WHERE marks.RowNum = 1
ORDER BY marks.Surname
结果


如果您正在学习SQL,请学习使用正确的、明确的、标准的联接语法。感谢您的回答,我学到了一点关于over和partition by的知识,但实际上我问的是稍微不同的事情,我希望每个学生都有一个科目,他从中获得了最多的分数,而不是最高的分数,所以前学生a得到了3分、4分,5来自主题1和5,2来自主题2-因此结果表包含studentA | subject1 | 3为答案添加了更多信息,见下图。这实际上是我们在发明行数之前必须做的事情:分组并计算数据,将其连接回主数据,分组并最大化,使用窗口函数,它变得更简单,因为它是隐式完成的-将其视为一个窗口函数,如maxage overpartition by class,等效于学生加入的学校在student.class=a.class上按班级a从学生组中选择班级最大年龄-db计算每个班级的最大年龄,并将结果放入每一行,就像加入该表上分组的表格一样
SELECT  marks.Surname,
    marks.SubjectName,
    marks.Marks_count,
    ROW_NUMBER() OVER(PARTITION BY marks.Surname ORDER BY marks.Surname) as RowNum
FROM MarksAmountPerStudentAndSubject marks
INNER JOIN (SELECT MarksAmountPerStudentAndSubject.Id, 
            MAX(MarksAmountPerStudentAndSubject.Marks_count) as MaxAmount
        FROM MarksAmountPerStudentAndSubject
        GROUP BY MarksAmountPerStudentAndSubject.Id) m
ON m.Id = marks.Id and marks.Marks_count = m.MaxAmount
SELECT marks.Surname, marks.SubjectName, marks.Marks_count
FROM StudentsMaxMarksAmount marks
WHERE marks.RowNum = 1
ORDER BY marks.Surname