4

これは生データであり、スコア(count(tbl_1.id))に従ってランク付けする必要があります。

[tbl_1]
===========
id | name  
===========
1  | peter
2  | jane
1  | peter
2  | jane
3  | harry
3  | harry
3  | harry
3  | harry
4  | ron

したがって、各IDのスコアをカウントするための一時テーブル(tbl_2)を作成します。

SELECT id, name, COUNT( id ) AS score
FROM tbl_1
GROUP BY id
ORDER BY score DESC;
LIMIT 0, 30;

その結果は次のとおりです。

[tbl_2]
===================
id | name  | score
===================
3  | harry | 4
1  | peter | 2
2  | jane  | 2
4  | ron   | 1

次に、これをクエリします。

SELECT v1.id, v1.name, v1.score, COUNT( v2.score ) AS rank
FROM votes v1
JOIN votes v2 ON v1.score < v2.score
OR (
v1.score = v2.score
AND v1.id = v2.id
)
GROUP BY v1.id, v1.score
ORDER BY v1.rank ASC, v1.id ASC
LIMIT 0, 30;

その結果は次のとおりです。

==========================
id | name  | score | rank
==========================
3  | harry | 4     |  1
1  | peter | 2     |  2
2  | jane  | 2     |  2
4  | ron   | 1     |  4

これを1つのトランザクション(クエリ)でうまく行うことは可能ですか?

4

1 に答える 1

2

はい、1回のクエリでこれを行うことができます。ただし、MySQLには単純なROWNUM操作がなく、ランク計算に必要なため、これはMySQLの完全なヘアボールです。

ランクが表示された投票クエリは次のとおりです。@ranka変数は、行に番号を付けるために使用されます。

SELECT @ranka:=@ranka+1 AS rank, id, name, score
  FROM
  (
     SELECT id, 
            name, 
            COUNT( id ) AS score
       FROM tbl_1
       GROUP BY id
       ORDER BY score DESC, id
   ) votes,
  (SELECT @ranka:=0) r

すでに発見したように、適切なランキング(タイを正しく処理する)を取得するには、このことを自己参加する必要があります。したがって、クエリを取得し、votesテーブルへの2つの参照をそれぞれ独自のバージョンのこのサブクエリに置き換えると、必要なものが得られます。

SELECT v1.id,
       v1.name,
       v1.score,
       COUNT( v2.score ) AS rank
  FROM (
         SELECT @ranka:=@ranka+1 AS rank,
                id,
                name,
                score
           FROM
              (
                SELECT id,
                       name,
                       COUNT( id ) AS score
                  FROM tbl_1
                 GROUP BY id
                 ORDER BY score DESC, name
               ) votes,
         (SELECT @ranka:=0) r) v1
  JOIN (
         SELECT @rankb:=@rankb+1 AS rank, 
                id, 
                name, 
                score
           FROM
              (
                SELECT id,
                       name,
                       COUNT( id ) AS score
                  FROM tbl_1
                  GROUP BY id
                  ORDER BY score DESC, name
              ) votes,
        (SELECT @rankb:=0) r) v2 
    ON (v1.score < v2.score) OR 
       (v1.score = v2.score  AND v1.id = v2.id)
 GROUP BY v1.id, v1.score
 ORDER BY v1.rank ASC, v1.id ASC
 LIMIT 0, 30;

毛玉だと言った。行番号付けを正しく機能させるには、自己結合している2つのバージョンのサブクエリで異なる@ranka変数と@rankb変数が必要であることに注意してください。これらの変数には、MySQLではサブクエリスコープではなく接続スコープがあります。

http://sqlfiddle.com/#!2/c5350/1/0は、これが機能していることを示しています。

編集: PostgreSQLのRANK()関数を使用してこれを行う方がはるかに簡単です。

SELECT name, votes, rank() over (ORDER BY votes)
  FROM (
        SELECT name, count(id) votes
          FROM tab
         GROUP BY name
       )x

http://sqlfiddle.com/#!1/94cca/18/0

于 2012-08-06T18:49:50.740 に答える