34

だから私は次のようなテーブルを持っています:

ID_STUDENT | ID_CLASS | GRADE
-----------------------------
   1       |    1     |  90
   1       |    2     |  80
   2       |    1     |  99
   3       |    1     |  80
   4       |    1     |  70
   5       |    2     |  78
   6       |    2     |  90
   6       |    3     |  50
   7       |    3     |  90

次に、それらをグループ化、並べ替え、並べ替えて、次のようにする必要があります。

ID_STUDENT | ID_CLASS | GRADE | RANK
------------------------------------
    2      |    1     |  99   |  1
    1      |    1     |  90   |  2
    3      |    1     |  80   |  3
    4      |    1     |  70   |  4
    6      |    2     |  90   |  1
    1      |    2     |  80   |  2
    5      |    2     |  78   |  3
    7      |    3     |  90   |  1
    6      |    3     |  50   |  2

here のように一時変数を使用してランク付けできることがわかりましたが、グループ化されたセットに対してはどうすればよいですか? 洞察をありがとう!

4

7 に答える 7

40
SELECT id_student, id_class, grade,
   @student:=CASE WHEN @class <> id_class THEN 0 ELSE @student+1 END AS rn,
   @class:=id_class AS clset
FROM
  (SELECT @student:= -1) s,
  (SELECT @class:= -1) c,
  (SELECT *
   FROM mytable
   ORDER BY id_class, id_student
  ) t

これは非常にわかりやすい方法で機能します。

  1. 最初のクエリは、id_class最初、id_student2番目の順に並べられます。
  2. @studentおよび@classに初期化されます-1
  3. @class次のセットが入力されているかどうかをテストするために使用されます。(に格納されている)の前の値がid_class(に格納されて@classいる)現在の値と等しくない場合id_class@studentはゼロになります。それ以外の場合はインクリメントされます。
  4. @classに新しい値が割り当てられid_class、次の行のステップ3のテストで使用されます。
于 2009-02-10T16:05:26.213 に答える
14

Quassnoiのソリューションに問題があります(ベストアンサーとしてマークされています)。

私は同じ問題を抱えており(つまり、MySQLでSQLウィンドウ関数をシミュレートしています)、ユーザー定義変数を使用して前の行の値を格納することで、Quassnoiのソリューションを実装していました...

しかし、MySQLのアップグレードなどの後、私のクエリは機能しなくなりました。これは、SELECTのフィールドの評価順序が保証されていないためです。@class割り当ては、SELECTの後に配置されている場合でも、@student割り当ての前に評価できます。

これは、MySQLのドキュメントで次のように説明されています。

原則として、ユーザー変数に値を割り当てたり、同じステートメント内で値を読み取ったりしないでください。期待どおりの結果が得られる場合がありますが、これは保証されていません。ユーザー変数を含む式の評価の順序は未定義であり、特定のステートメントに含まれる要素に基づいて変更される可能性があります。さらに、この順序は、MySQLサーバーのリリース間で同じであるとは限りません。

ソース:http ://dev.mysql.com/doc/refman/5.5/en/user-variables.html

最後に、私はそのようなトリックを使用して、それを読んだ後に必ず@classを割り当てます:

SELECT id_student, id_class, grade,
   @student:=CASE WHEN @class <> id_class THEN concat(left(@class:=id_class, 0), 0) ELSE @student+1 END AS rn
FROM
  (SELECT @student:= -1) s,
  (SELECT @class:= -1) c,
  (SELECT *
   FROM mytable
   ORDER BY id_class, grade desc
  ) t

left()関数の使用は、@class変数を設定するために使用されます。次に、left()の結果(NULLに等しい)を期待される結果に連結します。これは透過的です。

あまりエレガントではありませんが、機能します!

于 2012-11-27T16:51:53.287 に答える
7
SELECT g1.student_id
     , g1.class_id
     , g1.grade
     , COUNT(*) AS rank
  FROM grades   AS g1
  JOIN grades   AS g2
    ON (g2.grade, g2.student_id) >= (g1.grade, g1.student_id)
   AND g1.class_id = g2.class_id
 GROUP BY g1.student_id
        , g1.class_id
        , g1.grade
 ORDER BY g1.class_id
        , rank
 ;

結果:

+------------+----------+-------+------+
| student_id | class_id | grade | rank |
+------------+----------+-------+------+
|          2 |        1 |    99 |    1 |
|          1 |        1 |    90 |    2 |
|          3 |        1 |    80 |    3 |
|          4 |        1 |    70 |    4 |
|          6 |        2 |    90 |    1 |
|          1 |        2 |    80 |    2 |
|          5 |        2 |    78 |    3 |
|          7 |        3 |    90 |    1 |
|          6 |        3 |    50 |    2 |
+------------+----------+-------+------+
于 2012-10-08T08:18:15.973 に答える
5

上から変更すると、これは機能しますが、必要と思われるよりも複雑です。

SELECT ID_STUDENT, ID_CLASS, GRADE, RANK
FROM
    (SELECT ID_STUDENT, ID_CLASS, GRADE,
        @student:=CASE WHEN @class <> id_class THEN 1 ELSE @student+1 END AS RANK,
        @class:=id_class AS CLASS
    FROM
        (SELECT @student:= 0) AS s,
        (SELECT @class:= 0) AS c,
        (SELECT * 
            FROM Students
            ORDER BY ID_CLASS, GRADE DESC
        ) AS temp
    ) AS temp2
于 2009-02-10T16:25:38.847 に答える
1

私はいくつかの検索を行いましたが、この記事がこの解決策を思い付くことがわかりました:

SELECT S2.*, 
FIND_IN_SET(
S2.GRADE
, (
SELECT GROUP_CONCAT(GRADE ORDER BY GRADE DESC)
FROM Students S1
WHERE S1.ID_CLASS = S2.ID_CLASS
)
) AS RANK
FROM Students S2 ORDER BY ID_CLASS, GRADE DESC;

どちらが良いかについて何か考えはありますか?

于 2009-02-10T16:40:10.950 に答える