2014-05-17 6 views
0

here과 같이 환상의 야구 포인트를 계산하는 PostgreSQL 쿼리를 작성하려고합니다. 내가 지금까지 가지고있는 것은 this SQLfiddle에서 사용할 수 있는데, 이는 동률의 경우를 제외하고 각 통계에 대한 포인트를 올바르게 계산합니다. 묶인 팀의 점수는 다음과 같이 계산되어야합니다 :rotisserie 야구 포인트를 계산하기위한 PostgreSQL 쿼리

동점 인 경우, 위의 예에서 두 팀이 합계 점수를 얻었습니다 각 카테고리는 9.5 포인트 (10 + 9)/2 = 9.5 포인트를 받게된다.

내 접근 방식에서의 오류는 내 SQLfiddle의 firstsecond 결과 집합에서 확인할 수 있습니다. 첫 번째 결과 세트에서 9 홈런을 맺은 팀은 각각 3.5 점 (4 위와 3 위 == 7을 2로 나눈 값)을 얻어야하며, 두 번째 세트에서는 33 타점으로 묶인 팀이 각각 3.5 (순위 5, 4, 3 및 2의 합계 == 14, 4로 나눈 값).

이러한 오류를 수정하고 각 통계의 순위에 묶인 팀간에 총점을 균등하게 분배하는 가장 간단한 방법은 무엇입니까?

+0

스키마에'hr'이 무엇이고'rbi'가 무엇인지 설명 할 수 있습니까? 또한 목표와 부동 소수점 ('9.5'와 같은)을 사용하는 경우 왜 'numeric'형식이 아닌'integer' 형식을 사용합니까? – vyegorov

+0

HR 및 RBI는 내가 순위를 매기려고하는 값입니다.이 경우에는 [home runs] (http://en.wikipedia.org/wiki/Home_run)과 [running in batted in] (http : // en. wikipedia.org/wiki/Run_batted_in) 야구 팀. 이것들은 정수이지만 동점의 경우 팀의 순위는 내 질문의 Yahoo 링크에서와 같이 함께 평균되어야합니다. – tonycpsu

답변

1

제공된 예제는 완전한 것이 아니며 제공된 필드 중에서 후보 키를 갖는 것이 좋습니다.

  1. any aggregate function as window one을 사용할 수 있습니다. 이렇게하면 하위 쿼리가 테이블의 모든 행을 계산할 필요가 없습니다.

    SELECT 
        hr,rbi, 
        rank() OVER h AS hr_rank, 
        row_number() OVER h AS hr_rn, 
        count(*) OVER() - rank() OVER h + 1 AS hr_aprx, 
        rank() OVER r AS rbi_rank, 
        row_number() OVER r AS rbi_rn, 
        count(*) OVER() - rank() OVER r + 1 AS rbi_aprx, 
        count(*) OVER() AS cnt 
    FROM 
        stats 
    WINDOW h AS (ORDER BY hr DESC), r AS (ORDER BY rbi DESC); 
    

    이 쿼리는 첫 2 개 쿼리와 동일한 정보를 제공합니다

다음 쿼리의 출력을 고려한다. 출력이 EXPLAIN (analyze, buffers) 인 경우 표가 한 번만 액세스되는 것을 볼 수 있습니다.

여기서 포인트 열을 %_aprx으로 지정했습니다.이 점은 대략적인 것으로 아직 평균을 계산해야합니다.

  1. 이제 추가 계산을 위해 데이터를 준비 했으므로 하위 쿼리를 사용해야합니다. 이는 데이터 그룹화에 %_aprx 열을 사용해야한다는 사실 때문입니다. 나는 더 나은 이름의 하위 쿼리를 찾았으므로 여기서 CTE을 사용할 것입니다. 나는 제로의 시리즈를 제거하는 floatavg() 전화의 유형을 결과로 변환하고있어

    WITH ranks AS (
        SELECT 
         hr, rbi, 
         rank() OVER h AS hr_rank, 
         row_number() OVER h AS hr_rn, 
         count(*) OVER() - rank() OVER h + 1 AS hr_aprx, 
         rank() OVER r AS rbi_rank, 
         row_number() OVER r AS rbi_rn, 
         count(*) OVER() - rank() OVER r + 1 AS rbi_aprx, 
         count(*) OVER() AS cnt 
        FROM 
         stats 
        WINDOW h AS (ORDER BY hr DESC), r AS (ORDER BY rbi DESC) 
    ) 
    SELECT 
        hr, rbi, 
        (avg(hr_rn) OVER h)::float AS hr_pts, 
        (avg(rbi_rn) OVER r)::float AS rbi_pts, 
        (avg(hr_rn) OVER h + avg(rbi_rn) OVER r)::float AS ttl_pts 
    FROM 
        ranks 
    WINDOW h AS (PARTITION BY hr_aprx), r AS (PARTITION BY rbi_aprx) 
    ORDER BY 
        ttl_pts DESC, hr_pts DESC; 
    

    :

이 쿼리 (also on sql-fiddle)를 고려한다. 여기에 대신 use round() function을 선택할 수 있습니다.

또한 주문 조건을 2 개 추가했습니다. 이는 주문시 ttl_pts으로 충분하지 않습니다.

외부 쿼리의 창 정의에서 ORDER BY은 누락되었습니다. 이를 통해 평균 효과를 얻을 수 있습니다 (쿼리를 변경하고 자신을 볼 수 있음).

+0

Brilliant! 예, 나의 예는 약간의 세부 사항을 놓치고 있었지만, 의도적으로 그렇습니다. 이 쿼리를 실행하는 "테이블"은 실제로 개별 게임의 팀 결과를 집계하는 또 다른 복잡한 중첩 쿼리의 결과이기 때문에 "최소한의 작업 예제"로 처리하지 않았습니다. 문제는 그보다 더 복잡해 보입니다. 귀하의 솔루션을 사용하여 집계 결과가있는 임시 테이블을 주기적으로 만들거나 집계 쿼리를 실행하도록 적용 할 수 있습니다. 감사! – tonycpsu

1

무력 방법은 다음과 같이 조정되지 않은 순위, 뭔가를 계산 할 수 있습니다

select hr, sum(raw)/count(*) 
    from (
     select hr, 
      (select count(*) + 1 from stats) - row_number() over (order by hr desc) as raw 
     from stats 
    ) r 
group by hr 
order by hr desc 

주어진 점수 포인트를 얻을 수있는 통계 테이블과 그 가입 할 수 있습니다.

+0

좋은 시작이지만, 10 개의 통계 각각에 대해 하위 조인 (조인 포함)을 반복하는 것은 상당히 어렵습니다. 잘하면 더 쉬운 방법이 있습니다. – tonycpsu

+0

SQL에서 Unwieldy가 자주 발생하는 것은 아닙니다. 어쩌면 그것은 stats 열이 매개 변수 인 어떤 식 으로든 함수로 바뀔 수 있습니다. –

+0

Postgres는 내부 하위 쿼리를 반복적으로 스캔하지 않아도 될만큼 똑똑합니다. 'EXPLAIN' 결과물을보고이를 확인할 수 있습니다. – vyegorov