2

Student在 SQL Server 中有一个包含这些列的表:

[ID], [Age], [Level] 

我希望查询返回出现在 中的每个年龄值Students,并找到最常出现的级别值。例如,如果'a'18 岁的水平学生多于 'b' 或 'c' 它应该打印 pair (18, a)

我是 SQL Server 的新手,我想要一个简单的嵌套查询答案。

4

4 回答 4

5

您可以使用窗口函数执行此操作:

select t.*
from (select age, level, count(*) as cnt,
             row_number() over (partition by age order by count(*) desc) as seqnum
      from student s
      group by age, level
     ) t
where seqnum = 1;

内部查询聚合数据以计算每个年龄的级别数。row_number()枚举每个年龄的这些(最大partition by的第一个)。然后该where子句选择最高值。

在平局的情况下,这仅返回其中一个值。如果您想要所有这些,请使用rank()而不是row_number().

于 2013-06-01T15:04:15.113 回答
1
with combinations as (
  select age, level, count(*) occurrences
  from Student
  group by age, level
)
select age, level
from combinations c
where occurrences = (select max(occurrences)
                     from combinations
                     where age = c.age)

这会在学生表中找到每个年龄和级别组合,并计算每个级别的出现次数。然后,对于每个年龄/级别组合,找到在该年龄/级别组合中出现次数最多的那个。返回该行的年龄和级别。

这具有不与 SQL Server 绑定的优势——它是普通的 SQL。但是,像 Gordon 指出的窗口函数可能在 SQL Server 上执行得更好。

于 2013-06-01T16:22:51.143 回答
1

ORDER BY 子句中的 ROW_NUMBER 排名函数的另一个选项。当您想要返回两个或更多在有限结果集中并列最后一位的行时,使用 WITH TIES。

SELECT TOP 1 WITH TIES age, level
FROM dbo.Student
GROUP BY age, level
ORDER BY ROW_NUMBER() OVER(PARTITION BY age ORDER BY COUNT(*) DESC)

或者第二个版本的查询使用每对年龄和级别的数量,以及每个年龄的计数对年龄和级别的最大值。

SELECT *
FROM (
      SELECT age, level, COUNT(*) AS cnt, 
             MAX(COUNT(*)) OVER(PARTITION BY age) AS mCnt
      FROM dbo.Student
      GROUP BY age, level
      )x
WHERE x.cnt = x.mCnt

SQLFiddle上的演示

于 2013-06-01T16:54:10.507 回答
1

另一种选择,但需要更高版本的 sql-server:

;WITH x AS
(
SELECT  age, 
        level, 
        occurrences = COUNT(*) 
FROM    Student
GROUP BY age, 
        level
)
SELECT *
FROM   x x
WHERE  EXISTS (
              SELECT * 
              FROM   x y
              WHERE  x.occurrences > y.occurrences
              )

我意识到它并不能完全回答这个问题,因为它只返回年龄/级别组合,其中年龄有多个级别。

也许有人可以帮助修改它,使其在结果集中包含单级年龄:http ://sqlfiddle.com/#!3/d597b/9

于 2013-06-01T18:38:20.687 回答