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 回答
-1

因此,如果您的问题只是您不希望两个具有相同 id 的记录不应该彼此相邻,我认为最简单的是使用

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

或者您甚至可以使用 2 以外的其他数字来满足您想要的任何特定顺序....

于 2013-05-31T08:44:00.220 回答