3

その構造を持つ'user_score'テーブルがあります。

|id|user_id|group_id|score|     timestamp      |
| 1|      1|       1|  500| 2013-02-24 18:00:00|
| 2|      2|       1|  200| 2013-02-24 18:01:50|
| 3|      1|       2|  100| 2013-02-24 18:06:00|
| 4|      1|       1| 6000| 2013-02-24 18:07:30|

私がする必要があるのは、正確なグループからのそのテーブルからすべてのユーザーを選択することです。そのグループの実際の(タイムスタンプによる)スコアとランクを選択します。

私が持っているのは(編集:Jocachinのコメントの後、私自身のクエリが期待どおりに機能しないことがわかりました。すべての人に申し訳ありません):

SELECT user_id, score, @curRank := @curRank + 1 AS rank
FROM (
    SELECT * 
    FROM (
           SELECT * FROM `user_score`
           WHERE `group_id` = 1
           ORDER BY `timestamp` DESC
    ) AS sub2
    GROUP BY `user_id`
) AS sub, (SELECT @curRank := 0) r
ORDER BY `rank`

たとえばdataおよびgroup_id=1の期待される結果:

|user_id|score|rank|
|      1| 6000|   1|
|      2|  200|   2|

しかし、MySQLの副選択は少し問題があります。他に解決策はありますか?

後で、グループ内の単一ユーザーのランクを取得する必要があります。私は今迷っています。

4

4 に答える 4

5

このコンテキストで「問題がある」とはどういう意味かはわかりませんがLEFT JOIN、最後にランキングを正しく取得するために、サブクエリを使用してプレーンとして書き直されたクエリを次に示します(ORDER BYランキングの前に実行する必要があります)。

SELECT user_id, score, @rank := @rank + 1 AS rank FROM
(
  SELECT u.user_id, u.score
  FROM user_score u
  LEFT JOIN user_score u2
    ON u.user_id=u2.user_id
   AND u.`timestamp` < u2.`timestamp`
  WHERE u2.`timestamp` IS NULL
  ORDER BY u.score DESC
) zz, (SELECT @rank := 0) z;

でテストするSQLfiddle

編集:group_idを考慮に入れるには、クエリをいくらか拡張する必要があります。

SELECT user_id, score, @rank := @rank + 1 AS rank FROM
(
  SELECT u.user_id, u.score
  FROM user_score u
  LEFT JOIN user_score u2
    ON u.user_id=u2.user_id
   AND u.group_id = u2.group_id       -- u and u2 have the same group
   AND u.`timestamp` < u2.`timestamp`
  WHERE u2.`timestamp` IS NULL
    AND u.group_id = 1                -- ...and that group is group 1
  ORDER BY u.score DESC
) zz, (SELECT @rank := 0) z;

別のSQLfiddle

于 2013-02-24T17:50:48.817 に答える
1
SELECT user_id, score, @rank := @rank + 1 AS rank 
FROM 
(
    SELECT 
        user_id AS user_id, 
        SUBSTRING_INDEX(GROUP_CONCAT(score ORDER BY timestamp DESC), ',', 1) 
            AS score 
    FROM user_score 
    WHERE group_id=1 
    GROUP BY user_id
) AS u, 
(
    SELECT @rank := 0
) AS r
ORDER BY score DESC;
于 2013-02-24T17:51:36.817 に答える
1

回答が投稿されて受け入れられたことは知っていますが、あなたの元のクエリについて言及する価値があると思います。

グループ化する場合、グループ化する列と、MAXやCOUNTなどの集計関数を持つ列のみを選択できます。他の列を選択することは技術的に間違っています。

どの行のデータを返すかが明確でないため、これは理にかなっています。Mysqlは、groupbyの最初の行のデータを返します。これがクエリが機能する理由です(内部サブクエリのタイムスタンプによる順序のため)。一方、SQLサーバーは例外を発生させます。

SQL Serverのアプローチは正しく、このタイプのクエリは避ける必要があると思います。

于 2013-02-24T19:35:20.503 に答える
0

私は今日同様の問題に遭遇し、受け入れられた答えを実装しようとして失敗した後、私はこのはるかに単純なクエリを実行しました

SELECT user_score.user_id, 
       MAX(user_score.score) AS score
FROM user_score 
WHERE user_score.group_id = 1 
GROUP BY user_score.user_id, 
         user_score.group_id
ORDER BY user_score.score DESC, 
         user_score.`timestamp` ASC
于 2018-05-29T18:53:45.340 に答える