2014-04-20 6 views
3

학기가 두 필드 (연도, 학기)에 의해 결정되는 가장 최근 학기의 회의 목록을 쿼리하려고합니다. 다음최대 열 찾기 복수 열

Otherfields Year Semester 
meeting1  2014 1 
meeting2  2014 1 
meeting3  2013 2 
... etc ... 
최대가 처음으로 올해 고려되어야한다으로

학기, 내 결과는 다음과 같아야합니다 : 불행하게도

Otherfields Year Semester 
meeting1  2014 1 
meeting2  2014 1 

간단하게 사용하여 다음 스키마의 기본 개요입니다 각 열의 MAX() 함수는 Year = 2014, Semester = 2를 찾기 위해 별도로 시도합니다. 이는 올바르지 않습니다. 중첩 된 서브 쿼리와 내부 조인을 사용하여 몇 가지 접근법을 시도했지만 제대로 작동하지 못했습니다. 이것을 해결하는 가장 직접적인 접근법은 무엇입니까?

+0

mysql' oracle' ??? – NoobEditor

+0

개인적으로, 본질적으로 일반 Calendar 테이블과 비슷한 1 년/학기 테이블을 만들 것입니다 (또는 하나의 필드로). 그런 다음이 학년도/학기 ID를이 테이블에 붙이십시오. _does_는 쿼리에 대한 추가 조인이 필요합니다 (한 학년/학기가 _probably_ 순차적이라는 것은 신뢰할 수없는 구현 세부 사항이지만 빠른 것이어야합니다). 또한 학기 시작/종료 날짜 등을 지정하기가 쉽습니다. –

답변

2

: 같은

이 출력을 가져옵니다

SELECT Year, Semester, RANK() OVER(ORDER BY Year DESC, Semester DESC) R 
FROM your_table; 

R이 부부 (년, 학기)의 "순위"를 포함하는 열 수 있습니다. 그러면 예를 들어, 필터로이 열을 사용할 수 있습니다

WITH TT AS (
    SELECT Year, Semester, RANK() OVER(ORDER BY Year DESC, Semester DESC) R 
    FROM your_table 
) 
SELECT ... 
FROM TT 
WHERE R = 1; 

당신이 계급 사이의 간격, 당신은 dense_rank 대신 rank의를 사용할 수 있습니다하지 않으려면.

이 답변은 사용자가 윈도우 기능을 제공하기에 충분히 앞선 RDBMS를 사용한다고 가정합니다.하지 MySQL의)

+0

나는 이것이 Oracle에서이 쿼리를 실행하는 데 가장 좋은 방법이라고 추측합니다. 호기심에서 RANK() 함수는 오라클 고유의 것입니까, 아니면 다른 DBMS 사이에서 이식 가능한 것입니까? (예 : MSSQL, PostgreSQL) – guhou

+0

윈도우 함수가있는 DBMS에 상응하는 것이 있어야하지만이 특정 쿼리를 작성하기 위해 PostgreSQL을 사용했습니다. –

1

이 작업을 수행 (및 중복 하위 쿼리를 회피) 할 수있는 더 effecient 방법이 있다면 나는 놀라지 않을 것이다, 그러나 이것은 당신에게 당신이 원하는 답변을 얻을 것이다 :

SELECT * FROM table WHERE Year = 
    (SELECT MAX(Year) FROM table) 
AND Semester = 
    (SELECT MAX(Semester) FROM table WHERE Year = 
     (SELECT MAX(Year) FROM table)) 
+0

예 - 이중 중첩 테이블을 수정하여 하위 쿼리 테이블 참조로 사용하고 조인으로 포함 할 수 있습니다. 오라클은 더 나은 운영이 가능하지만, 다른 dbs (MySQL과 같은)에서 작동합니다. –

0

왜 당신은 간단하지 않습니다 ORDER BY ???

그런 식으로 처리하는 것이 더 쉽고 덜 지저분 할 것입니다 !! :)

SELECT * FROM table 
Where Year = (Select Max(Year) from table) /* optional clause to select only 2014*/ 
Order by Semester ASC, Year DESC, Otherfields; /*numericaly lowest sem first. in case of sem clash, sort by descending year first  */ 

EDIT 경우, 2014 년에서 제한 결과를 필요

,

SELECT * FROM table 
Where Year = (Select Max(Year) from table) 
Order by Semester ASC, Year DESC, Otherfields 
LIMIT 10; 

(MySQL의에 대한 ) Limit 절을 사용 그것은 것이다 order 첫째, 다음을 한계 - 10을 얻으십시오, 그래서 제한된 결과 세트를 얻으십시오! 윈도우 함수를 사용

Otherfields Year Semester 
meeting1  2014 1 
meeting2  2014 1 
meeting1  2013 1 
meeting2  2013 2 
+0

이것은 지난 학기가 아닌 행을 제거하지 않습니다. –

+0

didnt는 u를 얻는다. .. u는 rephrase를 바꿀 수있다? – NoobEditor

+0

원래 포스터는 지난 학기의 포스터 만 필요로하는 반면 쿼리는 테이블의 모든 행을 반환합니다. –

1

여기에 포스트 그레스을이다 :이 지나친했습니다

with table2 as /*virtual temporary table*/ 
(
    select *, year::text || semester as yearsemester 
    from table 
) 
select Otherfields, year, semester 
from table2 
where (Otherfields, yearsemester) in 
(
    select Otherfields, max(yearsemester) 
    from table2 
    group by Otherfields 
) 
+0

더 나은 방법이없는 dbs에 대해서는 관련 필드를 결합하는 것이 가능하지만, 나머지 쿼리는 다르게 구성했을 것입니다. 그리고 문자열 대신 숫자 형식을 사용하여 성능 차이를 확인했을 것입니다. –

1

이 얻을 수있는 훨씬 간단한 방법이 :

SELECT Meeting.year, Meeting.semester, Meeting.otherFields 
FROM Meeting 
JOIN (SELECT year, semester 
     FROM Meeting 
     WHERE ROWNUM = 1 
     ORDER BY year DESC, semester DESC) MostRecent 
    ON MostRecent.year = Meeting.year 
    AND MostRecent.semester = Meeting.semester 

(및 working Fiddle)

참고 이것의 변형은 꽤 많이 작동합니다. 모두 dbs (하위 쿼리에서 제한 절을 지원하는 모든 항목). 여기에 예를 들어, MySQL 버전,이다 :

SELECT Meeting.year, Meeting.semester, Meeting.otherFields 
FROM Meeting 
JOIN (SELECT year, semester 
     FROM Meeting 
     ORDER BY year DESC, semester DESC 
     LIMIT 1) MostRecent 
    ON MostRecent.year = Meeting.year 
    AND MostRecent.semester = Meeting.semester 

(... 그리고 working fiddle)

일부 데이터가 in this answer이 오라클에 대한 확대됨에 있어야한다 감안할 때, 그리고 내가 바로 가기 주어진 (뿐만 아니라 다른 DBS를 의심 옵티마이 저가 취할 수 있습니다). 이것은 분할 절이 제공되지 않는 대부분의 경우에 (창 없음) ROW_NUMBER()과 같은 항목의 사용을 대체 할 수 있어야합니다.

이 쿼리는 저장 프로 시저에서 실행 된, 그래서 내가 나서서 쿼리의 나머지 전에 별도의 쿼리의 최대 년/학기를 발견

0

여기에 내 자신의 질문에 대답. 이것은 비효율적이며 비 효과적 일 가능성이 가장 높지만 가장 이해할 수있는 방법이기도합니다. 팀의 다른 구성원이 혼란스러워 할까 봐 걱정할 필요가 없습니다. 이 질문은 다른 많은 상황에 일반적으로 적용될 수 있으므로 여기에 남겨 두며 다른 대안을 제공하는 좋은 대답이있는 것으로 보입니다.

-- Find the most recent year. 
SELECT MAX(year) INTO max_year FROM meeting; 

-- Find the most recent semester in the year. 
SELECT MAX(semester) INTO max_semester FROM meeting WHERE year = max_year; 

-- Open a ref cursor for meetings in most recent year/semester. 
OPEN meeting_list FOR 
    SELECT otherfields, year, semester 
    FROM meeting 
    WHERE year = max_year 
    AND semester = max_semester;