如何在 MS SQL 服务器中明智地获得最高记录组?
How to get the top record group wise in MS SQL Server?
我有一个学生 table 和注册 table。每个学生可以有多个注册,但只有一个当前注册。如果我想获得学生的当前入学率,我必须 select 该学生的最高入学记录。
示例查询:
select top 1 enrollmentid
from enrollmenttable
where enrollmenttable.studentid = studentid
order by enrollmenttable.enrolldate desc
以上查询returns某学生当前在校情况。我想修改上面的查询,以便我可以检索多个学生的当前注册。 IE。我想 select 多个学生 ID 的前 1 记录。
您可以使用 outer apply
:
select e.*
from students s outer apply
(select top 1 e.*
from enrollments e
where e.studentid = s.studentid
order by enrollmentid desc
) e;
请注意,您的查询使用 TOP
而没有 ORDER BY
。这是一个坏习惯——它 returns 一个任意行,甚至可能在不同的执行中改变。一般来说,除非你真的非常清楚自己在做什么,否则总是使用 ORDER BY
和 TOP
。
您确实希望在查询中明确地对数据进行排序。我的偏好是这样的;
示例数据
CREATE TABLE #EnrolmentData (StudentID int, EnrolmentID int)
INSERT INTO #EnrolmentData (StudentID, EnrolmentID)
VALUES
(1,1001)
,(1,1002)
,(2,1003)
,(3,1004)
,(3,1005)
,(3,1006)
实际查询
SELECT
a.*
FROM
(
SELECT
StudentID
,EnrolmentID
,ROW_NUMBER() OVER(PARTITION BY StudentID ORDER BY StudentID, EnrolmentID) RowNum
FROM #EnrolmentData
) a
WHERE a.RowNum = 1
结果;
StudentID EnrolmentID RowNum
1 1001 1
2 1003 1
3 1004 1
您可以 运行 内部查询自己查看它在做什么(一旦您设置了临时 table)。您没有提到您正在使用的数据类型,因此您需要确保按正确的字段进行排序。如果您想要最大的 EnrolmentID(并且该字段是一个 int),那么只需在子查询中在它后面添加一个 DESC
。
使用 DESC 查询
SELECT
a.*
FROM
(
SELECT
StudentID
,EnrolmentID
,ROW_NUMBER() OVER(PARTITION BY StudentID ORDER BY StudentID, EnrolmentID DESC) RowNum
FROM #EnrolmentData
) a
WHERE a.RowNum = 1
结果
StudentID EnrolmentID RowNum
1 1002 1
2 1003 1
3 1006 1
使用以下查询获得所需结果。
WITH cte_enrollment
AS
(
SELECT ROW_NUMBER()OVER(PARTITION BY studentid ORDER BY enrolldate desc) AS RNO ,
studentid,enrollmentid,enrolldate
FROM student s
JOIN enrollmenttable e
ON e.studentid = s.studentid
)
SELECT studentid,enrollmentid,enrolldate
FROM cte_enrollment
WHERE RNO=1
我有一个学生 table 和注册 table。每个学生可以有多个注册,但只有一个当前注册。如果我想获得学生的当前入学率,我必须 select 该学生的最高入学记录。
示例查询:
select top 1 enrollmentid
from enrollmenttable
where enrollmenttable.studentid = studentid
order by enrollmenttable.enrolldate desc
以上查询returns某学生当前在校情况。我想修改上面的查询,以便我可以检索多个学生的当前注册。 IE。我想 select 多个学生 ID 的前 1 记录。
您可以使用 outer apply
:
select e.*
from students s outer apply
(select top 1 e.*
from enrollments e
where e.studentid = s.studentid
order by enrollmentid desc
) e;
请注意,您的查询使用 TOP
而没有 ORDER BY
。这是一个坏习惯——它 returns 一个任意行,甚至可能在不同的执行中改变。一般来说,除非你真的非常清楚自己在做什么,否则总是使用 ORDER BY
和 TOP
。
您确实希望在查询中明确地对数据进行排序。我的偏好是这样的;
示例数据
CREATE TABLE #EnrolmentData (StudentID int, EnrolmentID int)
INSERT INTO #EnrolmentData (StudentID, EnrolmentID)
VALUES
(1,1001)
,(1,1002)
,(2,1003)
,(3,1004)
,(3,1005)
,(3,1006)
实际查询
SELECT
a.*
FROM
(
SELECT
StudentID
,EnrolmentID
,ROW_NUMBER() OVER(PARTITION BY StudentID ORDER BY StudentID, EnrolmentID) RowNum
FROM #EnrolmentData
) a
WHERE a.RowNum = 1
结果;
StudentID EnrolmentID RowNum
1 1001 1
2 1003 1
3 1004 1
您可以 运行 内部查询自己查看它在做什么(一旦您设置了临时 table)。您没有提到您正在使用的数据类型,因此您需要确保按正确的字段进行排序。如果您想要最大的 EnrolmentID(并且该字段是一个 int),那么只需在子查询中在它后面添加一个 DESC
。
使用 DESC 查询
SELECT
a.*
FROM
(
SELECT
StudentID
,EnrolmentID
,ROW_NUMBER() OVER(PARTITION BY StudentID ORDER BY StudentID, EnrolmentID DESC) RowNum
FROM #EnrolmentData
) a
WHERE a.RowNum = 1
结果
StudentID EnrolmentID RowNum
1 1002 1
2 1003 1
3 1006 1
使用以下查询获得所需结果。
WITH cte_enrollment
AS
(
SELECT ROW_NUMBER()OVER(PARTITION BY studentid ORDER BY enrolldate desc) AS RNO ,
studentid,enrollmentid,enrolldate
FROM student s
JOIN enrollmenttable e
ON e.studentid = s.studentid
)
SELECT studentid,enrollmentid,enrolldate
FROM cte_enrollment
WHERE RNO=1