查询的自定义排序

Yan*_*hon 4 postgresql postgresql-9.3

我正在处理的应用程序根据状态和日期(按该顺序)显示一些任务。但是,对于特定状态,排序条件应该颠倒。例如,一个看起来像这样的表:

 id    | status   | planned_date
-------+----------+--------------
 1     | inactive | 2015-03-12
 2     | active   | 2015-03-13
 3     | inactive | 2015-03-13
 4     | inactive | 2015-03-14
 5     | active   | 2015-03-12
 6     | active   | 2015-03-16
 7     | active   | 2015-03-17
Run Code Online (Sandbox Code Playgroud)

应该返回为

 id    | status   | planned_date
-------+----------+--------------
 5     | active   | 2015-03-12
 2     | active   | 2015-03-13
 6     | active   | 2015-03-16
 7     | active   | 2015-03-17
 4     | inactive | 2015-03-14
 3     | inactive | 2015-03-13
 1     | inactive | 2015-03-12
Run Code Online (Sandbox Code Playgroud)

注意:为了让这个例子简单起见,只使用了两个状态,但这是enum该字段的 6 个不同值的迭代;new, pending, active, inactive, cancelled, completed. 此外,还有其他字段需要排序:planned_date, 和priority(从-3到的数值30为“正常”)。我提到这只是一个仅供参考,因为我认为它没有太大的相关性,并且可以通过上面的简单示例来理解总体思路。

要按status字段 (an enum)排序,我只需执行

SELECT id, status, planned_date
FROM tbl_tasks
WHERE ...
ORDER BY status ASC;
Run Code Online (Sandbox Code Playgroud)

现在,我该如何排序planned_date字段(ASCactive状态和DESCinactive状态)?

Sim*_*stö 8

您可以使用CASE WHEN运算符来解决这个问题:

ORDER BY status,
    CASE status
        WHEN 'active' THEN planned_date - now()
        WHEN 'inactive' THEN now() - planned_date
    END
Run Code Online (Sandbox Code Playgroud)


ype*_*eᵀᴹ 5

另一种方法是使用ROW_NUMBER()

select *
from t
order by status,
         case status 
             when 'active'   then  1 
             when 'inactive' then -1
         end 
         * row_number() over (partition by status order by planned_date) ; 
Run Code Online (Sandbox Code Playgroud)

SQLfiddle测试