按视图限制排序,然后按另一列排序

Order by views limiting, then order by another column

我有一个查询从我的数据库中选择 * 按视图排序并限制为 4:

SELECT * FROM articles WHERE visible = 1 ORDER BY views LIMIT 4;

但在同一个查询中,我想查找按列 updated_at 排序的所有其他行。

我试过这样的东西,但不起作用:

(SELECT * FROM articles ORDER BY views DESC LIMIT 4)
UNION
(SELECT * FROM articles ORDER BY updated_at DESC);

建议这是"pinning"主页上最热门的4篇文章,然后按时间排序已更新。

有没有办法在同一个查询中以多种方式进行 ORDER BY 而不重复行?

我该怎么做?

您可以使用逗号分隔多个 ORDER 命令。 MySQL将从左到右排序。

SELECT * FROM articles WHERE visible = 1 ORDER BY views, updated_at DESC LIMIT 4;

继续您当前的想法,我们可以采用两个子查询的并集。第一个子查询是您已经包含在问题中的内容,并找到 4 篇更常被查看的文章。第二个子查询查找其他所有内容。这里的技巧是在每个子查询中包含一个计算字段,我们可以使用它来跟踪前 4 条记录。然后,我们首先按此计算字段排序,然后按 updated_at 字段排序。

(
    SELECT a.*, 1 AS label
    FROM articles a
    WHERE visible = 1
    ORDER BY views DESC
    LIMIT 4
)
UNION ALL
(
    SELECT a.*, 2
    FROM articles a
    WHERE visible = 1
    ORDER BY views DESC
    LIMIT 1000000 OFFSET 4    -- the limit 1000000 is arbitrary; just use a number
)                              -- larger than the expected size of your table
ORDER BY
    label, views, updated_at

来自 MySQL documentation:

... The default behavior for UNION is that duplicate rows are removed from the result. ...

... If ORDER BY appears without LIMIT in a SELECT, it is optimized away because it will have no effect anyway. ...

所以这里的技巧是在第二个查询中使用limit(由您选择限制):

(SELECT * FROM articles WHERE visible = 1 ORDER BY views DESC LIMIT 4)
UNION
(SELECT * FROM articles WHERE visible = 1 ORDER BY updated_at DESC LIMIT 100);

查询已在 MySQL 5.6 和 5.7 中测试。