子查询解决方法中可能的 "limit n/select top n" 限制
Possible "limit n/select top n" limitation within subquery workaround
我有以下案例(我演示的示例是在虚拟域上,因为 NDA 等原因)。
我可以访问包含以下形状的学生数据的生产数据库:
Student_ID Course_Name Total_Average_Grade
1 Maths 19,1
1 Physics 0
1 Biology 0
2 Physics 18,5
2 Chemistry 0
3 Maths 19,4
3 Literature 0
3 Physics 0
我想检索总平均成绩最高的 10 名学生,并为这 10 名检索他们所修课程的完整列表。我想 运行 这个查询每月一次。
例如,在上面的 table 中,如果我想 select 前 2 名学生,输出将是:
Student_ID Course_Name Total_Average_Grade
3 Maths 19,4
3 Physics 0
3 Biology 0
1 Maths 19,1
1 Literature 0
1 Physics 0
请注意,我无权在此数据库上创建视图或存储过程,这是克服无法对 (select top n / limit n) selection(例如,我将能够自动创建一个月度视图,我将使用它来加入普通的 select 前 10 个平均值等)。
这个任务有什么优雅的解决方案吗?
郑重声明,我使用 Sybase 15.4 作为客户端来访问 Sybase IQ 生产数据库。
我想你可以使用这样的查询:
select *
from (
select *,
row_number() over (partition by Course_Name order by Total_Average_Grade desc) as rn
from yourTable) t
where t < 11;
检查以下在 SQL 服务器上成功运行的查询。
DECLARE @student TABLE(
Student_ID INT,
Course_Name VARCHAR(100),
Total_Average_Grade VARCHAR(100)
)
INSERT INTO @student
select 1, 'Maths ' ,'19.1' union
select 1, 'Physics' ,'0'union
select 1, 'Biology' ,'0'union
select 2, 'Physics' ,'18.5'union
select 2, 'Chemistry' ,'0'union
select 3, 'Maths' ,'19.4'union
select 3, 'Literature' ,'0'union
select 3, 'Physics' ,'0'
;WITH ValList AS(
SELECT Student_ID,Course_Name, Case when Total_Average_Grade like '%,%' then
CAST(LEFT(Total_Average_Grade,PATINDEX('%,%', Total_Average_Grade) - 1) AS float)
else Total_Average_Grade end as
Total_Average_Grade,
RIGHT(Total_Average_Grade,LEN(Total_Average_Grade) - PATINDEX('%,%', Total_Average_Grade)) Remainder
FROM @student
UNION ALL
SELECT Student_ID,Course_Name,
CAST(LEFT(Remainder,CASE WHEN PATINDEX('%,%', Remainder) = 0 THEN LEN(Remainder) ELSE PATINDEX('%,%', Remainder) - 1 END) AS float) Total_Average_Grade,
RIGHT(Remainder,CASE WHEN PATINDEX('%,%', Remainder) = 0 THEN 0 ELSE LEN(Remainder) - PATINDEX('%,%', Remainder) END) Remainder
FROM ValList
WHERE LEN(Remainder) > 0
)
select SS.* from @student SS
join
(
SELECT top 2 v.Student_ID -- use TOP 10 for 10 records
--,s.Course_Name,s.Total_Average_Grade,SUM(v.Total_Average_Grade) as Avg,
,row_number() over( order by SUM(v.Total_Average_Grade) desc) rnk
FROM ValList V
join @student S on s.Student_ID=V.Student_ID and s.Course_Name=V.Course_Name
GROUP BY v.Student_ID
)AA on AA.Student_ID=SS.Student_ID
order by rnk asc,Total_Average_Grade desc
OutPut :
我有以下案例(我演示的示例是在虚拟域上,因为 NDA 等原因)。
我可以访问包含以下形状的学生数据的生产数据库:
Student_ID Course_Name Total_Average_Grade
1 Maths 19,1
1 Physics 0
1 Biology 0
2 Physics 18,5
2 Chemistry 0
3 Maths 19,4
3 Literature 0
3 Physics 0
我想检索总平均成绩最高的 10 名学生,并为这 10 名检索他们所修课程的完整列表。我想 运行 这个查询每月一次。
例如,在上面的 table 中,如果我想 select 前 2 名学生,输出将是:
Student_ID Course_Name Total_Average_Grade
3 Maths 19,4
3 Physics 0
3 Biology 0
1 Maths 19,1
1 Literature 0
1 Physics 0
请注意,我无权在此数据库上创建视图或存储过程,这是克服无法对 (select top n / limit n) selection(例如,我将能够自动创建一个月度视图,我将使用它来加入普通的 select 前 10 个平均值等)。
这个任务有什么优雅的解决方案吗?
郑重声明,我使用 Sybase 15.4 作为客户端来访问 Sybase IQ 生产数据库。
我想你可以使用这样的查询:
select *
from (
select *,
row_number() over (partition by Course_Name order by Total_Average_Grade desc) as rn
from yourTable) t
where t < 11;
检查以下在 SQL 服务器上成功运行的查询。
DECLARE @student TABLE(
Student_ID INT,
Course_Name VARCHAR(100),
Total_Average_Grade VARCHAR(100)
)
INSERT INTO @student
select 1, 'Maths ' ,'19.1' union
select 1, 'Physics' ,'0'union
select 1, 'Biology' ,'0'union
select 2, 'Physics' ,'18.5'union
select 2, 'Chemistry' ,'0'union
select 3, 'Maths' ,'19.4'union
select 3, 'Literature' ,'0'union
select 3, 'Physics' ,'0'
;WITH ValList AS(
SELECT Student_ID,Course_Name, Case when Total_Average_Grade like '%,%' then
CAST(LEFT(Total_Average_Grade,PATINDEX('%,%', Total_Average_Grade) - 1) AS float)
else Total_Average_Grade end as
Total_Average_Grade,
RIGHT(Total_Average_Grade,LEN(Total_Average_Grade) - PATINDEX('%,%', Total_Average_Grade)) Remainder
FROM @student
UNION ALL
SELECT Student_ID,Course_Name,
CAST(LEFT(Remainder,CASE WHEN PATINDEX('%,%', Remainder) = 0 THEN LEN(Remainder) ELSE PATINDEX('%,%', Remainder) - 1 END) AS float) Total_Average_Grade,
RIGHT(Remainder,CASE WHEN PATINDEX('%,%', Remainder) = 0 THEN 0 ELSE LEN(Remainder) - PATINDEX('%,%', Remainder) END) Remainder
FROM ValList
WHERE LEN(Remainder) > 0
)
select SS.* from @student SS
join
(
SELECT top 2 v.Student_ID -- use TOP 10 for 10 records
--,s.Course_Name,s.Total_Average_Grade,SUM(v.Total_Average_Grade) as Avg,
,row_number() over( order by SUM(v.Total_Average_Grade) desc) rnk
FROM ValList V
join @student S on s.Student_ID=V.Student_ID and s.Course_Name=V.Course_Name
GROUP BY v.Student_ID
)AA on AA.Student_ID=SS.Student_ID
order by rnk asc,Total_Average_Grade desc
OutPut :