2011-03-25 2 views
0

I는 다음과 같습니다 스키마가 있습니다 SQL 산술과 결합 세 개의 열은

+----------+ 
| tour  | 
+----------+ 
| id  | 
| name  | 
+----------+ 

+----------+ 
| golfer | 
+----------+ 
| id  | 
| name  | 
| tour_id | 
+----------+ 

+-----------+ 
| stat  | 
+-----------+ 
| id  | 
| round  | 
| score  | 
| golfer_id | 
+-----------+ 

그래서 본질적으로 골프 투어가에서 골프를 치는 사람의 X 번호가 있습니다. 골퍼는 X 개의 통계를 갖습니다. 상태 표의 원형 열에는 숫자 (1, 2, 3, 4 ... 등) 만 있습니다. 그들은 반드시 다른 하나 다음에 반드시있는 것은 아니지만 그들은 독특합니다.

이제는 "PGA"투어에 속한 모든 골퍼와 각 골퍼를 찾고 마지막 2 라운드에서 점수를 계산하고 싶습니다. 마지막 2 라운드는 근본적으로 가장 큰 두 숫자가있는 골퍼를위한 상태 테이블의 행입니다. 그래서 "Tiger Woods"라는 골퍼가 1, 3, 6, 10 라운드에서 경기를했다고 가정 해 봅시다. 6 라운드와 10 라운드에서 점수를 계산하고 싶습니다. 또 다른 요구 사항은 아직까지 골퍼에게 보여주고 싶지 않다는 것입니다. 적어도 두 차례에 걸쳐서 연주 했어.

나는 이것을 얻으려는 몇 가지 방법을 시도했지만 항상 자신을 얽히게했습니다.

답변

2

마지막 두 라운드 ("2"강조)를 원할 경우 간단한 트릭이 있습니다. 이 트릭은 두 개 이상 또는 두 개가 아닌 레코드로 확장되지 않습니다. 파티션에서 임의의 레코드를 얻으려면 더 많은 관여가 있으며 최신 버전의 주류 데이터베이스 엔진에서만 지원되는 창 기능을 사용해야합니다.

트릭은 "stat"테이블을 골퍼 ID에서 자체 조인하는 것입니다. 같은 라운드를 가지고도 만들 조합

SELECT s1.round as s1_round, s2.round AS s2_round 
FROM stat s1 INNER JOIN stat s2 ON (s1.golfer_id = s2.golfer_id) 

은 그럼 당신은 (WHERE 절을 통해)을 제외 :이 방법은, 같은 라운드 조합을 포함하여, 골퍼의 두 라운드의 모든 조합을 얻을 이 조합은 항상 1 라운드> 2 라운드라는 것을 명심하십시오. 이것은 이제 더 중복으로, 골퍼의 두 라운드의 모든 조합을 가지고 있다는 것을 의미 :

SELECT s1.round as s1_round, s2.round AS s2_round FROM stat s1 INNER JOIN stat s2 ON (s1.golfer_id = s2.golfer_id) WHERE s1.round > s2.round 

주의

당신은 특정 골퍼만을 기록과 종류 DESC 두 개의 둥근 기둥에, 상단을 선택하면 행은 그 골퍼의 마지막 두 라운드가 될 것입니다 :

SELECT TOP 1 s1.round as s1_round, s2.round AS s2_round 
FROM stat s1 INNER JOIN stat s2 ON (s1.golfer_id = s2.golfer_id) 
WHERE s1.round > s2.round 
ORDER BY s1.round DESC, s2.round DESC 

TOP 1 상단 행을 얻기 위해 SQL 서버 용어입니다. MySQL의 경우 LIMIT 1을 사용해야합니다. 다른 데이터베이스의 경우 데이터베이스 엔진의 특별한 방법을 사용하십시오.

그러나이 경우 모든 골퍼의 마지막 두 라운드가 필요하므로 간단하게 처리 할 수 ​​없습니다. 더 많은 조인을 수행해야합니다.

이렇게하면 각 골퍼에 대해 마지막 두 라운드 (두 열에 있음)가 제공됩니다.

또는 두 개의 열 임시 세트 골퍼 테이블에 합류하는 것도 작동합니다 :

SELECT golfer.id, MAX(r.s1_round) AS last_round, MAX(r.s2_round) AS second_to_last_round 
FROM golfer INNER JOIN 
(
SELECT s1.golfer_id AS golfer_id, s1.round AS s1_round, s2.round AS s2_round 
FROM stat s1 INNER JOIN stat s2 ON (s1.golfer_id = s2.golfer_id) 
WHERE s1.round > s2.round 
) r ON (r.golfer_id = golfer.id) 
GROUP BY golfer.id 

나는 PGA 투어 골퍼를 얻기 위해 여행 테이블이 쿼리에 가입 사소한 운동으로두고, 이 쿼리를 통계 테이블에 다시 결합하여 마지막 두 라운드의 점수를 얻습니다.

+0

+1 매우 섹시한 답변입니다. – Hogan

+0

@Hogan, 감사합니다. 이것은 창 함수가 있기 전에 수년 동안 사용해 온 트릭입니다. 마지막 두 레코드를 찾으려고 할 때 매우 효율적입니다. 그룹화의 각 레코드에 대해 마지막 두 개를 찾으려고 할 때 효율적이지 않습니다. –

2

HSQLDB 2.1은 임의의 조건으로 선택을 허용하는 LATERAL 조인을 지원합니다.

간단한은 PGA 투어의 모든 골퍼를 나열합니다 가입 : 당신은 특정 점수를 필요로하는

select golfer.name from tour join golfer on (tour.id = tour_id and tour.name = 'PGA') 

당신은 다음과 같은 몇 번이 테이블에 가입 측면. 다음 예는 다음 예에서 (재생 라운드를 플레이 한 경우에만) 마지막 라운드의 점수

select golfer.name, firststat.score from tour join golfer on (tour.id = tour_id and tour.name = 'PGA'), 
lateral(select * from stat where golfer_id = golfer.id order by round desc limit 1) firststat 

를 포함, 당신은 마지막으로 한 라운드를 포함하는 결합 횡 방향 하나 이상을 사용하십시오. 은 "조건이 여기서"목록에서의 테이블에서 가져온 때문에, 측면 가입

select golfer.name, secondstat.score score1, firststat.score score2 from tour join golfer on (tour.id = tour_id and tour.name = 'PGA'), 
lateral(select * from stat where golfer_id = golfer.id order by round desc limit 1 offset 1) secondstat, 
lateral(select * from stat where golfer_id = golfer.id order by round desc limit 1) firststat 

가 WHERE 절을 필요로하지 않는다 : 플레이어가 두 라운드를 palyed하지 않은 경우, 플레이어에 대한 행이 없을 것 현재 테이블 앞에 표시됩니다. 따라서 LATERAL 테이블의 하위 쿼리에있는 SELECT 문은 첫 번째 조인 된 테이블의 golfer.id를 사용할 수 있습니다.

관련 문제