문제

나는 매우 큰 테이블의 측정 데이터에서 MySQL 고 계산하는 백분위에 대한 각자의 이러한 값입니다.Oracle 을 가지고 나타나 함수 호출 percent_rank 그러나 나는 아무것도 찾을 수 없습니다 비슷한 MySQL.확인 할 수 있는 brute-force 에서는 파이썬 내가 사용하는 어쨌든 테이블을 채우지만 내가 의심되는 것이 매우 비효율적이기 때문에 하나의 샘플 수 있습 200.000 관찰.

도움이 되었습니까?

해결책

이것은 비교적 추악한 대답이며, 나는 죄책감을 느낍니다. 즉, 문제에 도움이 될 수 있습니다.

백분율을 결정하는 한 가지 방법은 모든 행을 계산하고 제공 한 숫자보다 큰 행의 수를 계산하는 것입니다. 더 크거나 적은 것을 계산하고 필요에 따라 역수를 취할 수 있습니다.

번호에 인덱스를 만듭니다. Total = Select Count (); Less_equal = select count () 여기서 값> indexed_number;

백분율은 다음과 같습니다 : Less_equal / Total 또는 (Total -Less_equal) / Total

둘 다 생성 한 색인을 사용하고 있는지 확인하십시오. 그렇지 않다면, 그들이 될 때까지 조정하십시오. 설명 쿼리에는 오른쪽 열에 "색인 사용"이 있어야합니다. SELECT COUNT (*)의 경우 innodb에 인덱스를 사용하고 MyISAM의 Const와 같은 색인을 사용해야합니다. Myisam 은이 값을 계산하지 않고도 언제든지 알 것입니다.

데이터베이스에 저장된 백분율이 필요한 경우 위의 설정을 성능을 위해 사용한 다음 두 번째 쿼리를 내부 선택으로 사용하여 각 행의 값을 계산할 수 있습니다. 첫 번째 쿼리 값은 상수로 설정할 수 있습니다.

이것이 도움이됩니까?

야곱

다른 팁

조인이 필요하지 않은 다른 접근법은 다음과 같습니다. 제 경우 (15,000+ 이상의 표) 행은 약 3 초 안에 실행됩니다. (결합 방법은 크기가 더 오래 걸립니다).

샘플에서 가정하십시오 측정하다 백분율 순위를 계산하는 열이며 ID 단지 행 식별자입니다 (필요하지 않음) :

SELECT
    id,
    @prev := @curr as prev,
    @curr := measure as curr,
    @rank := IF(@prev > @curr, @rank+@ties, @rank) AS rank,
    @ties := IF(@prev = @curr, @ties+1, 1) AS ties,
    (1-@rank/@total) as percentrank
FROM
    mytable,
    (SELECT
        @curr := null,
        @prev := null,
        @rank := 0,
        @ties := 1,
        @total := count(*) from mytable where measure is not null
    ) b
WHERE
    measure is not null
ORDER BY
    measure DESC

이 방법에 대한 크레딧은 Shlomi Noach로 이동합니다. 그는 여기에 자세히 글을 씁니다.

http://code.openark.org/blog/mysql/sql-ranking-without-self-join

나는 이것을 MySQL에서 테스트했으며 훌륭하게 작동합니다. Oracle, SQLServer 등에 대해 전혀 모릅니다.

이 작업을 수행하는 쉬운 방법은 없습니다. 보다 http://rpbouman.blogspot.com/2008/07/calculating-nth-percentile-in-mysql.html

SELECT 
    c.id, c.score, ROUND(((@rank - rank) / @rank) * 100, 2) AS percentile_rank
FROM
    (SELECT 
    *,
        @prev:=@curr,
        @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;

SQL을 PHP와 같은 절차 언어와 결합하는 경우 다음을 수행 할 수 있습니다. 이 예는 초과 비행 블록 시간을 공항으로, 백분위 수로 분류합니다. MySQL의 한계 x, y 절을 사용하여 ORDER BY. 그다지 예쁘지는 않지만 직장을 수행합니다 (죄송합니다. 서식으로 고생했습니다) :

$startDt = "2011-01-01";
$endDt = "2011-02-28";
$arrPort= 'JFK';

$strSQL = "SELECT COUNT(*) as TotFlights FROM FIDS where depdt >= '$startDt' And depdt <= '$endDt' and ArrPort='$arrPort'";
if (!($queryResult = mysql_query($strSQL, $con)) ) {
    echo $strSQL . " FAILED\n"; echo mysql_error();
    exit(0);
}
$totFlights=0;
while($fltRow=mysql_fetch_array($queryResult)) {
    echo "Total Flights into " . $arrPort . " = " . $fltRow['TotFlights'];
    $totFlights = $fltRow['TotFlights'];

    /* 1906 flights. Percentile 90 = int(0.9 * 1906). */
    for ($x = 1; $x<=10; $x++) {
        $pctlPosn = $totFlights - intval( ($x/10) * $totFlights);
        echo "PCTL POSN for " . $x * 10 . " IS " . $pctlPosn . "\t";
        $pctlSQL = "SELECT  (ablk-sblk) as ExcessBlk from FIDS where ArrPort='" . $arrPort . "' order by ExcessBlk DESC limit " . $pctlPosn . ",1;";
        if (!($query2Result = mysql_query($pctlSQL, $con)) ) {
            echo $pctlSQL  . " FAILED\n";
            echo mysql_error();
            exit(0);
        }
        while ($pctlRow = mysql_fetch_array($query2Result)) {
            echo "Excess Block is :" . $pctlRow['ExcessBlk'] . "\n";
        }
    }
}

MySQL8 마지막으로 소개 창 기능,그리고 그 중 PERCENT_RANK() 는 기능을 찾고 있었던 것입니다.그래서 그냥:

SELECT col, percent_rank() OVER (ORDER BY col)
FROM t
ORDER BY col

당신의 질문을 언급"백분위"는 약간 다른 것입니다.완전성을 위해'술,거기에 PERCENTILE_DISCPERCENTILE_CONT 역 분포의 기능에서 SQL 표준과 어 RBDMS(Oracle,PostgreSQL,SQL Server,Teradata)지만,MySQL.MySQL8 창능 당신을 에뮬레이션 할 수 있습니다 PERCENTILE_DISC, 그러나 다시 사용하여 PERCENT_RANKFIRST_VALUE 창수.

계급을 얻으려면 (왼쪽) 외부 테이블 자체에 참여해야한다고 말합니다.

select t1.name, t1.value, count(distinct isnull(t2.value,0))  
from table t1  
left join table t2  
on t1.value>t2.value  
group by t1.name, t1.value 

각 행에 대해, 동일한 테이블의 몇 개의 행에 값이 열등한 수를 계산합니다.

SQLServer에 더 익숙하므로 구문이 옳지 않을 수 있습니다. 또한 뚜렷한 것은 당신이 달성하고자하는 것에 대한 올바른 행동을 가질 수 있습니다. 그러나 이것이 일반적인 아이디어입니다.
그런 다음 실제 백분위 수 순위를 얻으려면 먼저 변수 (또는 취할 규칙에 따라 뚜렷한 값)에서 값 수를 얻고 위에 주어진 실제 순위를 사용하여 백분위 수 순위를 계산해야합니다.

다음과 같은 판매 테이블이 있다고 가정합니다.

user_id, 단위

그런 다음 다음 쿼리는 각 사용자의 백분위 수를 제공합니다.

select a.user_id,a.units,
(sum(case when a.units >= b.units then 1 else 0 end )*100)/count(1) percentile
from sales a join sales b ;

이로 인해 크로스 조인이 발생하므로 O (N2) 복잡성이 발생하므로 최적화되지 않은 솔루션으로 간주 될 수 있지만 MySQL 버전에 기능이 없다는 점에서 간단 해 보입니다.

이 무엇인지 op 을 의미하는'백분위 순위',하지만 주어진 백분에 대한 설정 값보 http://rpbouman.blogspot.com/2008/07/calculating-nth-percentile-in-mysql.html Sql 계산할 수 쉽게 변경되었을 생산하는 다른 또는 여러 개의 백분위.

한 참고:를 변경했 계산 약간,예를 들어 90%-"90/100*COUNT(*)+0.5"대신에"90/100*COUNT(*)+1".때로는 그것이었다 건너뛰기 두 값이 과거의 백분위점에서 정렬된 목록을 선택하는 대신 다음으로 높은 가치를 위해 백분율.어쩌면 이 방법을 정수를 반올림에서 작동 mysql.

ie:

....SUBSTRING_INDEX(SUBSTRING_INDEX(GROUP_CONCAT(fieldValue ORDER BY fieldValue 구분','), ',', 90/100 * COUNT(*)+ 0.5),',',-1)로 90thPercentile....

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top