SQL로 순위 지정 -SELECT 문으로 순위 만들기

6661 단어 SQL데이터베이스

대상 독자


  • RANK 함수를 사용할 수없는 DBMS를 사용하는 사람 (Oracle, SQL Server, PostgreSQL은 RANK 함수로 실현 가능)
  • SQL을 사용하여 머리 체조를하고 싶은 분 (자신이라면 어떤 SQL을 쓰는지 생각해보십시오)

  • 순위 지정 대상(평균 연봉)



    중국·시코쿠 지방의 데이터를 사용해 보겠습니다.


    현명
    평균 연봉


    에히메현
    388만엔

    오카야마현
    385만엔

    히로시마현
    386만엔

    가가와현
    383만엔

    고치현
    379만엔

    야마구치현
    395만엔

    돗토리현
    386만엔

    시마네현
    369만엔

    도쿠시마현
    387만엔


    DODA 평균 연수 랭킹 2017(47 도도부현의 평균 연수)

    위의 데이터에서 다음과 같은 결과를 출력하려면 어떻게 해야 합니까?


    현명
    평균 연봉
    순위


    에히메현
    388만엔
    2

    오카야마현
    385만엔
    6

    히로시마현
    386만엔
    4

    가가와현
    383만엔
    7

    고치현
    379만엔
    8

    야마구치현
    395만엔
    1

    돗토리현
    386만엔
    4

    시마네현
    369만엔
    9

    도쿠시마현
    387만엔
    3


    순위 지정 SQL



    SQL 문



    실행 환경: MySQL 8.0.11
    --県名  :prefecture_name
    --平均年収:average_income
    SELECT
        i1.prefecture_name AS '県名'
        , i1.average_income AS '平均年収'
        , (SELECT count(i2.average_income)
            FROM income i2
            WHERE i1.average_income < i2.average_income) + 1 AS '順位'
    FROM
        income i1
    ORDER BY
        順位;
    

    출력 결과



    야마구치가 던트츠의 1위! 돗토리는 어떻게 했습니까?


    설명



    SELECT 절의 세 번째 열에서 "순위"를 생성합니다. 주 쿼리 (i1)의 각 행에 대해 하위 쿼리 (i2)를 실행하고 주 쿼리 (i1)의 행 평균 연수 수보다 큰 하위 쿼리 (i2)의 행 수를 계산합니다.

    예를 들어, 평균 연수입이 가장 높은 야마구치현은, 「WHERE i1.average_income < i2.average_income」를 평가해도 395만엔보다 큰 값은 나오지 않기 때문에, 부문의의 카운트 결과는 0건이 됩니다. 다만, 0위라고 하는 것은 순위로서 올바르지 않기 때문에, 카운트 결과에 +1해 순위로서 출력할 필요가 있습니다.

    평균 연수수가 같은 데이터가 복수 있는 경우는 같은 순위가 되고(돗토리현과 히로시마현), 그 다음의 데이터(오카야마현)의 순위는, 「직전의 순위+직전의 순위를 가지는 데이터의 개수」가 됩니다. 그림에서 말하면, 돗토리현과 히로시마현이 같은 4위이며, 그 다음의 오카야마현은 6위로 되어 있습니다.

    덤: 순위를 테이블에 유지



    순위는 다른 컬럼(이 경우는 평균 연수입)에서 구할 수 있는 도출 항목이기 때문에 컬럼으로서 유지하는 것은 별로 추천할 수 없습니다만 *1, 어떠한 이유로 필요한 경우도 있다고 생각하므로 쓰기 유지합니다.

    *1 도출 항목을 컬럼으로서 유지하는 경우, 도출원이 되는 데이터와 도출 항목의 무결성이 문제가 됩니다. 예를 들어, 파생 항목을 생성하는 것이 30분 간격이면 30분 동안 데이터 불일치가 발생할 수 있으므로 주의해야 합니다.
    덧붙여서, 일관성을 확보하는 수단의 하나로서 트리거가 있으므로 사용을 검토하는 것도 있습니다.
    트리거란 무엇인가 - 사용소와 문제점을 생각한다 -

    실행 환경: MySQL 8.0.11
    SET SQL_SAFE_UPDATES = 0; --SQLの制限を解除する
    
    UPDATE 
        income
        , (
            SELECT
                i1.income_id
                ,i1.prefecture_name AS '県名'
                , i1.average_income AS '平均年収'
                , (SELECT count(i2.average_income)
                    FROM income i2
                    WHERE i1.average_income < i2.average_income) + 1 AS '順位'
            FROM
                income i1
            ORDER BY
                順位
        ) income_rank
    SET
        income.rank = income_rank.順位
    WHERE
        income.income_id = income_rank.income_id;
    

    마지막으로



    RANK 함수를 채용하고 있는 DBMS가 늘어나고 있는 일도 있어, 당기사의 SQL을 실제로 사용할까라고 하면 미묘한 곳입니다만, 「이런 SQL의 사용법도 있을까」라고 생각해 주시면 다행입니다. 예를 들어, SELECT 문에서 SELECT 라는 것은 다른 목적의 SQL에도 응용할 수 있을지도 모릅니다. 응용할 수 있을 것 같은 용도를 생각해 보세요.

    참고문헌



    달인에게 배우는 SQL 철저 지남서

    좋은 웹페이지 즐겨찾기