我在SQL Server中有一个表Student
,其中包含以下列:
[ID], [Age], [Level]
我希望查询返回Students
中显示的每个年龄值,并查找最常出现的级别值。例如,如果18岁以上的'a'
级学生多于“b”或“c”,则应打印(18, a)
对。{/ p>
我是SQL Server的新手,我想要一个嵌套查询的简单答案。
答案 0 :(得分: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
子句选择最高值。
在tie的情况下,这只返回其中一个值。如果您想要所有这些内容,请使用rank()
代替row_number()
。
答案 1 :(得分: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)
这将查找Students表中的每个年龄和级别组合,并计算每个级别的出现次数。 然后,对于每个年龄/级别组合,找到该年龄/级别组合的出现次数最高的那个。返回该行的年龄和级别。
这样做的好处是不依赖于SQL Server - 它是纯粹的SQL。但是,像Gordon指出的窗口函数可能在SQL Server上表现更好。
答案 2 :(得分: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上的演示
答案 3 :(得分: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