MySQL中逻辑的备用顺序

时间:2016-11-16 21:07:02

标签: mysql

我希望通过mySQL允许自定义排序逻辑,允许以下数据集:

+----+-----------------+------------+-------+--+
| ID |      item       | Popularity | Views |  |
+----+-----------------+------------+-------+--+
|  1 | A special place |          3 |    10 |  |
|  2 | Another title   |          5 |    12 |  |
|  3 | Words go here   |          1 |    15 |  |
|  4 | A wonder        |          2 |     8 |  |
+----+-----------------+------------+-------+--+

要返回一个按行,逐行,按人气,然后按视图替换的订单,所以返回结果如下所示:

+----+-----------------+------------+-------+--+
| ID |      item       | Popularity | Views |  |
+----+-----------------+------------+-------+--+
|  3 | Words go here   |          1 |    15 |  |
|  2 | Another title   |          5 |    12 |  |
|  4 | A wonder        |          2 |     8 |  |
|  1 | A special place |          3 |    10 |  |
+----+-----------------+------------+-------+--+

你会看到第一行返回'最受欢迎',第二行返回最多的视图,第三行返回第二行最受欢迎,第四行返回第二行最多。

目前我正在通过mySQL两次收集整个表,然后在PHP中合并这些结果。当数据库很大时,这不会削减它。这在mysql中是否可行?

1 个答案:

答案 0 :(得分:0)

我想这些方面的东西都可行。请考虑以下事项:

DROP TABLE IF EXISTS my_table;

CREATE TABLE my_table
(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
,x INT NOT NULL
,y INT NOT NULL
);

INSERT INTO my_table VALUES
(1,3,10),
(2,5,12),
(3,1,15),
(4,2, 8)
(5,4, 1);

我们可以依次对x和y进行排名,然后将这些排名排列在一个列表中 - 因此将有x1,y1,x2,y2等 - 但所有行都会出现两次;一次为x级,一次为y级......

       SELECT * FROM 
       (
         ( SELECT a.*, COUNT(*) rank FROM my_table a JOIN my_table b ON b.x <= a.x GROUP BY a.id )
          UNION ALL
         ( SELECT a.*, COUNT(*) rank FROM my_table a JOIN my_table b ON b.y <= a.y GROUP BY a.id )
       ) n
       ORDER BY rank

       +----+---+----+------+
       | id | x | y  | rank |
       +----+---+----+------+
       |  5 | 4 |  1 |    1 |
       |  3 | 1 | 15 |    1 |
       |  4 | 2 |  8 |    2 |
       |  4 | 2 |  8 |    2 |
       |  1 | 3 | 10 |    3 |
       |  1 | 3 | 10 |    3 |
       |  5 | 4 |  1 |    4 |
       |  2 | 5 | 12 |    4 |
       |  2 | 5 | 12 |    5 |
       |  3 | 1 | 15 |    5 |
       +----+---+----+------+

现在我们可以抓住每个id的最低排名...

SELECT id
     , x
     , y
  FROM
     (
       ( SELECT a.*, COUNT(*) rank FROM my_table a JOIN my_table b ON b.x <= a.x GROUP BY a.id )
         UNION ALL
       ( SELECT a.*, COUNT(*) rank FROM my_table a JOIN my_table b ON b.y <= a.y GROUP BY a.id )
     ) m
 GROUP
    BY id,x,y
 ORDER
    BY MIN(rank);
+----+---+----+
| id | x | y  |
+----+---+----+
|  3 | 1 | 15 |
|  5 | 4 |  1 |
|  4 | 2 |  8 |
|  1 | 3 | 10 |
|  2 | 5 | 12 |
+----+---+----+         

顺便说一下,变量应该更快 - 但我目前无法使解决方案正常工作 - 也许是高级时刻。