2017-01-16 2 views
1

다음 사례가 있습니다 (NDA 이유로 인해 더미 도메인에있는 예입니다).하위 쿼리 해결 방법 내에서 가능한 "제한 n/선택 상위 n"제한

I 프로덕션 DB에 액세스 다음과 같은 모양으로 학생 데이터를 들고 있습니다

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)의 전체 목록을 검색 그들이 택한 코스. 매월이 쿼리를 실행하고 싶습니다. 나는 상위 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 

주 데이터베이스를 사용하면 (상위 n/제한 n 선택) 선택에서 하위 쿼리를 수행 할 수 없다는 한계를 극복하는 쉬운 방법이 될 수 있습니다 (예를 들어, 내가 가입 할 때 사용하는 월간보기를 자동으로 만들 수 있습니다) 일반 10 대 평균 선택 등).

이 작업에 대한 멋진 해결책이 있습니까?

레코드 용으로 Sybase I.4 제품 데이터베이스에 액세스하기 위해 Sybase 15.4를 클라이언트로 사용하고 있습니다.

+0

입력 테이블 –

+0

체크 출력 PLZ 샘플 출력을 추가한다. 학생 1은 19,4? 하지만 입력 테이블에서 19,1? –

+0

수정 됨 (복사 - 붙여 넣기로 인한 오류) – rpd

답변

1

난 당신이 같은 쿼리를 사용 할 수 있다고 생각 성공적으로 SQL 서버에서 실행되는 쿼리 아래

select * 
from (
    select *, 
     row_number() over (partition by Course_Name order by Total_Average_Grade desc) as rn 
    from yourTable) t 
where t < 11; 
+0

둘 다 작동하지만 첫 번째 솔루션은 훨씬 더 우아합니다. 필자는 분석 SQL 함수와 로직에 익숙하지 않습니다. 분석 함수를 사용할 때 생각한 것보다 훨씬 쉽습니다. – rpd

1

확인합니다.

 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 

출력 :

enter image description here