自定义MySQL订购

时间:2013-05-31 05:50:21

标签: php mysql sql

我有一个需要自定义排序的查询,减少到最低限度,例如:

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

但我希望它实际上像这样对SOMETHING进行排序(因此没有2个UserID与彼此相邻):

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

这对MySQL来说是否可能,或者我需要一些PHP魔法吗?

4 个答案:

答案 0 :(得分: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;

只要没有一个用户具有非常长的序列(如在您的示例中),这将起作用。

没有“始终有效”的解决方案,因为很容易想出一个无法实现目标的情况。

答案 1 :(得分: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)];
 }

答案 2 :(得分: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 |
+----+-----------+------+

答案 3 :(得分:-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以外的其他数字来满足您想要的任何订单....