2012-07-18 7 views
2

동일한 테이블 내에서 20 가지 다른 비교를 사용하는 MySQL SELECT 쿼리가 있습니다. SELECT 결과가 반환 내 SCORE라고 나는 컬럼의 순서에 따라 백분위 순위를 계산하기 위해 노력하고있어MySQL - 즉석에서 백분위 수 계산

SELECT * FROM mytable 
WHERE (col1 > (col2 * 0.25)) 
AND (col5 < col10) ....... 

예를 들면 다음과 같습니다이다. 나는 증분 행 번호와 COUNT(*)을 사용하여 주식의 순위와 결과의 총 개수를 얻으려고했지만 결과 중 일부가 동일한 계급을 할당하는 방법을 모르겠다. SCORE.

((COUNT(lower scores) + (COUNT(same/tied scores)/2)) * 100)/COUNT(total results) 

을 어떻게 즉석에서 백분위를 계산 같은 결과 행 내에서 낮은 점수, 같은/묶여 점수와 총 점수의 수를 찾을 수 있습니까 : 여기

내가 계산하기 위해 노력하고있어 공식이다 ?

내 응용 프로그램 관리자가 내 응용 프로그램 관리 영역 내에서 SELECT 문을 필요에 맞게 조정하기 때문에 저장 프로 시저 사용을 피하려고합니다.

답변

3

, 여기에 코드는 그 I 백분위 순위를 계산하기 위해 함께했다 (경우에 사람이 미래에이를 계산하고 싶어) : 내가 발견으로

SELECT 
    c.id, c.score, ROUND(((@rank - rank)/@rank) * 100, 2) AS percentile_rank 
FROM 
    (SELECT 
    *, 
     @prev:[email protected], 
     @curr:=a.score, 
     @rank:=IF(@prev = @curr, @rank, @rank + 1) AS rank 
    FROM 
     (SELECT id, score FROM mytable) AS a, 
     (SELECT @curr:= null, @prev:= null, @rank:= 0) AS b 
ORDER BY score DESC) AS c; 
+0

이 문을 UPDATE 문으로 변환하는 간단한 방법이 있습니까? 예를 들어 mytable에 "percentile"이라는 열이 있다고 가정하면 percentile_rank 결과를 각 행의 백분위 열에 저장하도록 명령문을 수정하는 방법이 있습니까? – Todd

2

여기에 SELECT : SQL: Rank without Self Join 동안 순위를 설명하는 게시물 (내 광산)이 있습니다.

행이 반복되는 동안에도 액세스되고 할당되는 사용자 정의 변수를 사용합니다. 같은 논리를 사용

, 그것은 미리보기로 등 총 점수, 서로 다른 점수의 번호를 포함하도록 확장 할 수있다, 여기에 전형적인 쿼리 : 위의 Shlomi의 코드를 사용하여

SELECT 
    score_id, student_name, score, 
    @prev := @curr, 
    @curr := score, 
    @rank := IF(@prev = @curr, @rank, @rank+1) AS rank 
FROM 
    score, 
    (SELECT @curr := null, @prev := null, @rank := 0) sel1 
ORDER BY score DESC 
; 
+0

안녕하세요. Shlomi. 답장을 보내 주셔서 감사합니다. 이것은 분명히 도움이되지만 백분위 수를 계산하기 위해 각 행에 총 순위를 제공하지는 않습니다. 어떻게 내가 그걸 할 수 있을지 아는가? 나는 또 다른 질문을 게시 : http://stackoverflow.com/questions/11545537/mysql-selecting-total-results-returned-in-each-row 그걸 알아낼 수 있지만 여전히 어디에도 가지 않습니다. – Zishan

+0

간단히 설명하기 위해 누적 된 다른 변수를 추가하십시오 (@total_rank : = @ total_rank + @current_rank). 그런 다음 엔트리 쿼리를 바깥 쿼리로 래핑하면 이제는 rank/@ total_rank를 사용할 수 있습니다. 이 간단한 설명이 도움이되기를 바랍니다. –

+0

감사합니다. Shlomi, 도움이되었습니다! – Zishan

1

Shlomi과 (Shlomi의 코드를 사용) Zishan에서 응답을 확실히, 정확한 결과를 제공하지 않습니다 알에 대한 결과 검토 내 아지 테이블. 다른 대답으로, 하나의 MySQL의 쿼리에서 백분위 순위를 계산하기 위해 분명히 불가능하다 : SQL rank percentile

사용자 정의 변수를 사용하는 Shlomi Noach 접근 방식은 않습니다 - 처음에 -는 상위 몇 %에 제대로 작동 것처럼 봐 순위는 낮지 만 테이블의 하위 순위 행은 빠르게 퇴색합니다. 내가 한 것처럼 데이터 결과를 직접 확인하십시오.

제안 더 나은 솔루션으로, 단일 SQL 문 내에서 사용자 정의 변수 를 사용 Shlomi의 접근 방식이 작동하지 않는 이유에 대해 롤랜드 보우만하여이 블로그 게시물을 참조 :

http://rpbouman.blogspot.com/2009/09/mysql-another-ranking-trick.html

를 그래서 나는 이 목적을 위해 Bouman의 코드를 수정했고 여기 PHP와 MySQL을 결합한 솔루션이 있습니다.

단계 1) 다음 두 쿼리를 제출하여 각 행의 절대 순위를 계산하고 저장합니다.

SET @@group_concat_max_len := @@max_allowed_packet; 

UPDATE mytable INNER JOIN (SELECT ID, FIND_IN_SET(
    score, 
     (SELECT GROUP_CONCAT(
      DISTINCT score 
      ORDER BY score DESC 
      ) 
     FROM mytable) 
     ) AS rank 
FROM mytable) AS a 
ON mytable.ID=a.ID 
SET mytable.rank = rank; 

단계 2 : 행의 총 수를 페치 (및 PHP 변수 $ 총 결과를 저장)

SELECT COUNT(ID) FROM mytable 

3 단계 : 절대치를 사용하는 테이블을 반복하는 PHP 루프를 사용 이러한 열 값을 저장하는 동안

SELECT ID, rank FROM mytable 

: 통해

3A) 루프 각 행에 대한 랭크는 행의 백분위 순위를 계산할 $ ID 및 PHP

에서 $ 순위

3B) 각 행의 실행에 관해서 : 아마

$sql = 'UPDATE mytable INNER JOIN (
      SELECT (100*COUNT(ID)/'.$total.') percentile 
      FROM mytable 
      WHERE rank >= '.$rank.' 
     ) a 
     ON mytable.ID = a.ID 
     WHERE mytable.ID='.$ID.' 
     SET mytable.percentile = a.percentile'; 

없는 가장 효율적인 방법,하지만 확실히 정확하고 내 경우부터 '점수'값이 업데이트되지 않습니다 매우 자주, 그래서 위의 스크립트를 cron 일괄 작업으로 실행하여 백분위 순위를 최신 상태로 유지합니다.