我正在尝试对我无法弄清楚的mysql查询进行一些排序。
id | status | created_at
------------------------
1 | open | 1348778070
2 | closed | 1348711241
3 | open | 1348839204
4 | closed | 1348738073
5 | banned | 1348238422
如何按照ASC顺序订购上表,以便首先打开'开放'记录;然后非开放记录在DESC顺序中排名第二?换句话说,根据某些条件有一个动态的二级排序方向吗?
我尝试了两个SELECT查询的UNION,并在其中进行排序,这不起作用,因为UNION默认生成一组无序的行。
此外,我已经尝试了一个伪列,从大数字中减去created_at时间戳,用于已关闭的状态记录,因此我可以按ORDER BY ASC获得结果,如下所示......
SELECT table.*, (table.created_at) as tmp_order FROM table
WHERE table.status = 'open'
UNION
SELECT table.*, (999999999 - table.created_at) as tmp_order FROM table
WHERE table.status = 'closed'
ORDER BY tmp_order ASC
这有效,但我觉得必须有更好的方法。理想情况下,解决方案不包括上面的随机大数
答案 0 :(得分:4)
<强>已更新强>
SELECT *
FROM tmp_order
ORDER BY FIELD(status, 'open') DESC,
CASE
WHEN status = 'open'
THEN created_at
ELSE (999999999 - created_at)
END
或
SELECT *
FROM tmp_order
ORDER BY FIELD(status, 'open') DESC,
CASE
WHEN status = 'open'
THEN created_at END,
CASE
WHEN status <> 'open'
THEN created_at END DESC
输出:
| ID | STATUS | CREATED_AT | ---------------------------- | 1 | open | 1348778070 | | 3 | open | 1348839204 | | 4 | closed | 1348738073 | | 2 | closed | 1348711241 | | 5 | banned | 1348238422 |
这是 SQLFiddle 演示。
答案 1 :(得分:1)
尝试:
SELECT id, status,
if (status = 'open', created_at, 999999999 - created_at) as tmp_order
FROM table
ORDER BY status, tmp_order
答案 2 :(得分:1)
这就是我要解决的问题:
SELECT
id, status, created_at
FROM
yourtable
ORDER BY
status DESC,
CASE WHEN status='open' THEN created_at END,
CASE WHEN status='closed' THEN created_at END DESC
答案 3 :(得分:0)
在您的情况下,您可以在一个查询中执行此操作,但通用解决方案适用于任何两个不同且无关的查询。排序是使用两个联合子查询,每个子查询都有自己的排序;
SELECT * FROM (
SELECT *
FROM table
WHERE table.status = 'open'
ORDER BY created_at DESC) x
UNION ALL
SELECT * FROM (
SELECT *
FROM table
WHERE table.status = 'closed'
ORDER BY created_at) y