3

別の方法でorder byを適用したい MySQL データベースのクエリから、特別な種類の要件を探しています。たとえば、フィールドuser_iduser_ratinguser_departmentを持つ DB で、次のデータを使用します。

+------------------------------------------------------+
|      user_id    |   user_rating  |  user_department  |
+------------------------------------------------------+
|         1       |        102     |         A         |
|         2       |        33      |         B         |
|         3       |        43      |         C         |
|         4       |        54      |         A         |
|         5       |        63      |         A         |
|         6       |        214     |         B         |
|         7       |        82      |         A         |
|         8       |        87      |         C         |
|         9       |        43      |         A         |
|         10      |        98      |         A         |
|         11      |        73      |         C         |
|         12      |        31      |         A         |
+------------------------------------------------------+

上記の構造を考えると、結果をeach_departmentuser_ratingの順にソートしたいのですが、各 user_department から最大 5 つのレコードが必要です。そのうちの最初の 3 つのレコードは評価の順に並べる必要がありますが、残りの 2 つはランダムにする必要があります。

したがって、上記の場合、出力は次のようになります。

+------------------------------------------------------+
|      user_id    |   user_rating  |  user_department  |
+------------------------------------------------------+
|         1       |       102      |         A         |
|         10      |        98      |         A         |
|         7       |        82      |         A         |
|         12      |        31      |         A         |
|         5       |        63      |         A         |
|         6       |       214      |         B         |
|         2       |        33      |         B         |
|         8       |        87      |         C         |
|         11      |        73      |         C         |
|         3       |        43      |         C         |
+------------------------------------------------------+

FIELD関数を使用するなど、カスタムオーダーのためにWebで利用できるオプションを試しましたが、ここではそれほど有用ではありませんでした。また、サブクエリを使用して解決しようとしましたが、MySql ではクエリで IN キーワードと LIMIT キーワードを一緒に使用できないため、そのオプションも実行可能に見えません。

これを解決するためのより良い/簡単な方法はありますか?

4

1 に答える 1

1

これはまさにあなたが探しているものではありませんが、1 つのアプローチを提供します。

アイデアはgroup_concat()、各部門の上位 5 つの値を 1 つの列に入れるために使用することです。この列の形式は次のとおりです。

user_id:rating

コンマで区切って、5 回まで繰り返します。次のように:

1:182,10:98,7:82,12:31,5:63

これを行うクエリは次のとおりです。

select user_department,
       substring_index(group_concat(concat(user_id, ':', user_rating)
                                    order by user_rating desc
                                   ), ',', 5)
from t
group by user_department;

これは、最後の 2 つの値のランダム化を処理しません。そして、すべてを一列に並べます。しかし、私はそれが役立つかもしれないと思いました。

私の次の試みは、技術的にはあなたが求めていることを実行しますが、最後の 2 つの「ランダムな」ユーザーが同じである可能性があるというリスクがあります。

上記と同じgroup_concat()トリックを使用します。ただし、次を使用して、リストから異なる値を選択することで、それを超えていますsubstring_index()

select u.user_id, user_id.user_rating, u.user_department
from (select (case when n.n in (1, 2, 3) or ud.numusers <= 5
                   then cast(substring_index(substring_index(users, ',', n.n), ',', -1) as unsigned)
                   else CAST(substring_index(substring_index(users, ',', 4 + rand()*(num_users - 3)), ',', -1) as unsigned)
              end) as user_id
      from (select user_department,
                   group_concat(user_id order by user_rating desc) as users,
                   count(*) as numusers
            from t
            group by user_department
           ) ud join
           (select 1 as n union all select 2 union all select 3 union all select 4 union all select 5
           ) n
           on n.n <= ud.numusers
    ) u join
    t
    on u.user_id = t.user_id
order by user_department, user_rating desc
于 2013-07-15T18:13:39.487 に答える