Mysql“复杂”排序

时间:2012-07-19 13:28:55

标签: mysql sorting

想象一下,你有两个这样的表:

mysql> SELECT * FROM theme;
+----+---------+------------+
| id | name    | sort_order |
+----+---------+------------+
|  1 | Theme 1 | 1          |
|  2 | Theme 2 | 2          |
|  3 | Theme 3 | 3          |
|  4 | Theme 4 | 4          |
|  5 | Theme 5 | 5          |
|  6 | Theme 6 | 6          |
|  7 | Theme 7 | 7          |
+----+---------+------------+

mysql> SELECT * FROM article;
+----+------------+---------------------+----------+
| id | title      | update_date         | theme_id |
+----+------------+---------------------+----------+
|  1 | Article 1  | 2012-06-29 15:29:50 |        6 |
|  2 | Article 2  | 2012-07-18 00:00:00 |        2 |
|  3 | Article 3  | 2012-07-19 00:00:00 |        4 |
|  4 | Article 4  | 2012-07-18 00:00:00 |        4 |
|  5 | Article 5  | 2012-07-18 00:00:00 |        1 |
|  6 | Article 6  | 2012-06-26 10:30:51 |        6 |
|  7 | Article 7  | 2012-07-18 15:17:08 |        6 |
|  8 | Article 8  | 2012-06-18 00:00:00 |        4 |
|  9 | Article 9  | 2012-07-18 15:48:28 |        1 |
| 10 | Article 10 | 2012-07-09 00:00:00 |        4 |
+----+------------+---------------------+----------+

每篇文章都是一对一主题。

您希望能够执行一个查询,该查询为您提供如下订购的文章列表:

  • 按主题sort_order
  • 排序的每个主题的第一篇最新文章
  • 按主题sort_order
  • 排序的每个主题的第二篇最新文章
  • 按主题sort_order
  • 排序的每个主题的第三篇最新文章
  • 等......

对于当前数据,它应该提供以下内容:

+----+------------+---------------------+----------+
| id | title      | update_date         | theme_id |
+----+------------+---------------------+----------+
|  9 | Article 9  | 2012-07-18 15:48:28 |        1 |
|  2 | Article 2  | 2012-07-18 00:00:00 |        2 |
|  3 | Article 3  | 2012-07-19 00:00:00 |        4 |
|  7 | Article 7  | 2012-07-18 15:17:08 |        6 |
|  5 | Article 5  | 2012-07-18 00:00:00 |        1 |
|  4 | Article 4  | 2012-07-18 00:00:00 |        4 |
|  1 | Article 1  | 2012-06-29 15:29:50 |        6 |
| 10 | Article 10 | 2012-07-09 00:00:00 |        4 |
|  6 | Article 6  | 2012-06-26 10:30:51 |        6 |
|  8 | Article 8  | 2012-06-18 00:00:00 |        4 |
+----+------------+---------------------+----------+

我几乎可以肯定有一种方法可以使用单个查询来完成此操作,但我无法弄明白。

你将如何实现这一目标?

2 个答案:

答案 0 :(得分:5)

这与MySQL中的分区排名问题有关。 MySQL中没有窗口排序函数,但通过变量可以成功解决泛型问题:

SELECT
  id,
  title,
  update_date,
  theme_id
FROM (
  SELECT
    *,
    @rnk := @rnk * (@last_theme = theme_id) + 1 AS rnk,
    @last_theme := theme_id
  FROM article, (SELECT @rnk := 0, @last_theme := 0) s
  ORDER BY theme_id, update_date DESC
) s
ORDER BY
  rnk, theme_id
;

上述查询都对行进行排名,然后使用排名对最终结果集进行排序。该查询首先检索来自article的行,theme_idupdate_date DESC对其进行排序,以指定排名数字。然后,当从排名的行集中进行选择时,会引入另一个最终的排序,这次是排名和theme_id

您可以尝试此查询at SQL Fiddle

答案 1 :(得分:0)

你能否做一篇文章加入主题'然后按update_date,sort_order?

排序