7

カスタムの並べ替えが必要なクエリがあり、次のような最小限に切り詰められています。

SELECT u.*, p.*, p.id as product_id
FROM users u, products p 
WHERE u.id = p.user_id
ORDER BY product_id DESC

そして、次のような一連の行が返されます。

UserID        ProductID
     2                5
     2                4
     3                3
     1                2
     1                1

しかし、私は実際にこのように何かを並べ替えたいと思っています(したがって、2つのユーザーIDが互いに隣接していません):

 UserID        ProductID
     1                2
     2                4
     3                3
     2                5
     1                1

これはMySQLでも可能ですか、それともPHPマジックが必要ですか?

4

4 に答える 4

1

この問題を解決する標準的な方法は、重複する行を列挙し、その値で並べ替えることです。

select t.*
from (SELECT u.*, p.*, p.id as product_id,
             row_number() over (partition by u.id order by (select NULL)) as seqnum
      FROM users u join
           products p 
           on u.id = p.user_id
     ) t
order by seqnum, id;

(あなたの例のように)非常に長いシーケンスを持っているユーザーがいない限り、これは機能します。

目標が不可能な状況が発生しやすいため、「常に機能する」ソリューションはありません。

于 2013-05-31T07:37:30.843 に答える
0

次のことを検討してください...

CREATE TABLE sortable(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,player_id INT NOT NULL);

INSERT INTO sortable(player_id) VALUES (1),(1),(2),(3),(4),(3),(3),(2),(1),(2),(4),(4);

SELECT * FROM sortable;
+----+-----------+
| id | player_id |
+----+-----------+
|  1 |         1 |
|  2 |         1 |
|  3 |         2 |
|  4 |         3 |
|  5 |         4 |
|  6 |         3 |
|  7 |         3 |
|  8 |         2 |
|  9 |         1 |
| 10 |         2 |
| 11 |         4 |
| 12 |         4 |
+----+-----------+

SELECT x.*,COUNT(*) rank FROM sortable x JOIn sortable y ON y.player_id = x.player_id AND y.id <= x.id GROUP BY x.id ORDER BY player_id,rank;
+----+-----------+------+
| id | player_id | rank |
+----+-----------+------+
|  1 |         1 |    1 |
|  2 |         1 |    2 |
|  9 |         1 |    3 |
|  3 |         2 |    1 |
|  8 |         2 |    2 |
| 10 |         2 |    3 |
|  4 |         3 |    1 |
|  6 |         3 |    2 |
|  7 |         3 |    3 |
|  5 |         4 |    1 |
| 11 |         4 |    2 |
| 12 |         4 |    3 |
+----+-----------+------+

SELECT x.*,COUNT(*) rank FROM sortable x JOIn sortable y ON y.player_id = x.player_id AND y.id <= x.id GROUP BY x.id ORDER BY rank;
+----+-----------+------+
| id | player_id | rank |
+----+-----------+------+
|  1 |         1 |    1 |
|  3 |         2 |    1 |
|  4 |         3 |    1 |
|  5 |         4 |    1 |
|  2 |         1 |    2 |
|  8 |         2 |    2 |
|  6 |         3 |    2 |
| 11 |         4 |    2 |
|  9 |         1 |    3 |
| 10 |         2 |    3 |
|  7 |         3 |    3 |
| 12 |         4 |    3 |
+----+-----------+------+
于 2013-07-25T09:48:22.627 に答える
0

ここで、並べ替えた結果を配列に取得します。次に、このようなことをします。

 $records = $res->fetchAll();
 $count = count($records);
 $records = array_chunk($records, ceil(count($records)/2);
 $unsorted = array();
 for($x = 0; $x < $count; $x++){
      $unsorted[] = $records[$x%2][floor($x/2)];
 }
于 2013-05-31T06:12:35.030 に答える