【问题标题】:PostgresSQL ORDER BY clause with CASE for sorted column带有 CASE 的 PostgresQL ORDER BY 子句用于排序列
【发布时间】:2019-03-26 03:10:54
【问题描述】:

我有一个简单的SELECT ORDER BY 查询形式,它使用CASE 创建排序的ID。 我参考了基于https://gist.github.com/cpjolicoeur/3590737 的两种方法并使用了其中一种。

SELECT id FROM tasks t ORDER BY 
CASE 
WHEN t.type = 'TypeA' THEN 1 
WHEN t.type = 'TypeB' THEN 2 
WHEN t.type = 'TypeC' THEN 3 
END, 
CASE 
WHEN t.state = 'Interrupted' THEN 4 
WHEN t.state = 'Terminated' THEN 5 
WHEN t.state = 'Completed' THEN 6
WHEN t.state = 'Killed' THEN 7
WHEN t.state = 'Warning' THEN 8
WHEN t.state = 'Starting' THEN 9
WHEN t.state = 'New' THEN 10
WHEN t.state = 'Running' THEN 11
END, 
modified ASC;

以上查询基于以下条件对 i​​d 进行排序:

  1. TypeA 与状态: 中断、终止、完成、终止、警告、启动、新建、运行
  2. TypeB 状态: 中断、终止、完成、终止、警告、启动、新建、运行
  3. TypeC 状态: 中断、终止、完成、终止、警告、启动、新建、运行

我现在需要根据以下排序条件修改此 sql:

  1. TypeA 的状态:Interrupted,Terminated,Completed,Killed
  2. TypeB 状态:Interrupted,Terminated,Completed,Killed
  3. TypeC 状态:中断、终止
  4. TypeA 状态:Warning,Starting,New,Running
  5. TypeB 状态:Warning,Starting,New,Running
  6. TypeC 状态:Completed,Killed,Warning,Starting,New,Running

请注意“状态”的顺序(如指定)对于“类型”在这里同样重要

我正在尝试修改上面的 sql 以使其符合新标准。作为一个 sql 专家,我正在寻找最有效的方法来重写这个 sql,它也可以在不久的将来适应排序标准的细微变化。

为了进一步阐明下面的共享示例:

样本数据

id  | type  |    state
----+-------+-------------
 1  | TypeC | Completed
 2  | TypeA | Completed
 3  | TypeA | Running
 4  | TypeB | Completed
 5  | TypeB | Running
 6  | TypeC | Terminated
 7  | TypeC | Unknown
 8  | TypeA | Completed
 9  | TypeB | Interrupted
 10 | TypeB | Completed
 11 | TypeB | Interrupted
 12 | TypeC | Killed
 13 | TypeC | Running
 14 | TypeB | Warning
 15 | TypeB | Running
 16 | TypeB | Killed

预期数据

id  | type  |    state
--- +-------+-------------
 1  | TypeA | Completed
 8  | TypeA | Completed
 9  | TypeB | Interrupted
 11 | TypeB | Interrupted
 4  | TypeB | Completed
 10 | TypeB | Completed
 16 | TypeB | Killed
 7  | TypeC | Unknown
 6  | TypeC | Terminated
 3  | TypeA | Running
 14 | TypeB | Warning
 5  | TypeB | Running
 15 | TypeB | Running
 1  | TypeC | Completed
 12 | TypeC | Killed
 13 | TypeC | Running

【问题讨论】:

    标签: sql postgresql


    【解决方案1】:

    也许是这样的?

    CASE 
    WHEN t.type = 'TypeA' AND t.state 
            IN ( 'Interrupted','Terminated','Completed','Killed') 
      THEN 1
    WHEN t.type = 'TypeB' AND t.state 
            IN ( 'Interrupted','Terminated','Completed','Killed') 
      THEN 2
    ..
    ..
    

    编辑

    我建议您创建一个层次结构表,这样您的查询会变得更简单。

    CREATE TABLE type_state_hier AS
    select *  FROM 
    (
     VALUES
    (1,'TypeA','Interrupted'),
    (2,'TypeA','Terminated'),
    (3,'TypeA','Completed'),
    (4,'TypeA','Killed'),
    (5,'TypeB','Interrupted'),
    (6,'TypeB','Terminated'),
    (7,'TypeB','Completed'),
    (8,'TypeB','Killed'),
    (9,'TypeC','Interrupted'),
    (10,'TypeC','Terminated'),
    (11,'TypeA','Warning'),
    (12,'TypeA','Starting'),
    (13,'TypeA','New'),
    (14,'TypeA','Running'),
    (15,'TypeB','Warning'),
    (16,'TypeB','Starting'),
    (17,'TypeB','New'),
    (18,'TypeB','Running'),
    (19,'TypeC','Completed'),
    (20,'TypeC','Killed'),
    (21,'TypeC','Warning'),
    (22,'TypeC','Starting'),
    (23,'TypeC','New'),
    (24,'TypeC','Running')
    ) As s(rnk,type,state)
    ;
    

    现在,通过与主表的简单连接来查询它。

    select t.* from tasks t 
      join type_state_hier h on 
      h.type=t.type and h.state = t.state
    order by h.rnk ,t.id
    

    如果您不想创建表,只需将其用作 CTE(参考演示)

    DEMO

    【讨论】:

    • 它是否确保实现所需的状态排序?
    • @akhi :我怎么知道?您提到了它,但没有提供任何示例数据/预期输出来描述您的问题。
    • 好的,所以 IN 确保匹配是根据我们指定的顺序完成的,即大括号 (1,2 ,3,4...)
    • @akhi :它没有。正如我所说,你的问题没有说清楚。
    • 抱歉,如果不清楚,已添加注释并编辑了问题。实际上,原始查询也确保了状态的顺序。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-05-31
    • 2014-11-20
    • 1970-01-01
    • 1970-01-01
    • 2021-07-20
    • 2021-12-13
    • 2021-05-28
    相关资源
    最近更新 更多