PostgreSQL通过步进数字排序

时间:2016-02-23 21:23:14

标签: sql postgresql sorting

我需要按列从表中订购记录。客户使用的旧系统是手动选择的level 1项,然后是level 2的1级​​项目的所有子项,然后依次为level 5。这是可怕的恕我直言,因为它需要数百个查询和调用数据库。

所以在新的数据库结构中,如果可能的话,我试图让它向数据库进行一次查询,并让它第一次正确排序。客户希望以这种方式向他们展示,所以我别无选择,只能想办法以这种方式订购。

这是项目及其等级代码的示例(1为单位数代码,2为2位数代码,3为4位数代码,4为6位数代码,5级为8位数代码):

enter image description here

基本上应该命令以5开头的所有内容都在代码5下面。以51开头的所有东西都在代码51下。如果你看一下n_mad_id列它会链接到“母亲”ID代码是该代码的母亲,因此代码51的母亲是代码5.代码5101的母亲是代码51.代码5201的母亲是代码52.依此类推。

然后n_nivel列是代码所属的级别。每个代码都有一个级别和一个母亲。顶级代码(即1,2,3,4,5)都是1级,因为它们只有一位数。

我希望有一种简单的ORDER BY方法可以做到这一点。我已经玩了两天了,似乎无法服从它。

2 个答案:

答案 0 :(得分:1)

绝对最简单的方法是将n_cod字段转换为text,然后按顺序排序:

SELECT *
FROM mytable
WHERE left(n_cod::text, 1) = '5' -- optional
ORDER BY n_cod::text;

不漂亮,但功能齐全。

您可以考虑更改表定义以使n_cod类型为char(8),因为您无论如何都不会将其用作数字(在执行计算的意义上)。这会使查询更快。

答案 1 :(得分:0)

有趣的任务。据我所知,你想得到像

那样的结果
n_id   n_cod n_nivel n_mad_id  
  10       5       1        0
  11      51       2       10
  12    5101       3       11
  14  510101       4       12
...
  13      52       2       10
...

如果是,那么它可以做到这一点:

with recursive 
  tt(n_id, n_mad_id, n_cod, x) as (
    select t.n_id, t.n_mad_id, t.n_cod, array[t.n_id] 
    from yourtable t where t.n_mad_id = 0
    union all
    select t.n_id, t.n_mad_id, t.n_cod, x || t.n_id 
    from tt join yourtable t on t.n_mad_id = tt.n_id)
select * from tt order by x;

这是我原来的测试查询:

create table t(id, parent) as values
  (1, null),
    (3, 1),
      (7, 3),
      (5, 3),
        (6, 5),
  (2, null),
    (8, 2), 
    (4, 2);

with recursive 
  tt(id, parent, x) as (
    select t.id, t.parent, array[t.id] from t where t.parent is null
    union all
    select t.id, t.parent, x || t.id from tt join t on t.parent = tt.id)
select * from tt order by x;

及其结果:

 id | parent |     x     
----+--------+-----------
  1 | (null) | {1}
  3 |      1 | {1,3}
  5 |      3 | {1,3,5}
  6 |      5 | {1,3,5,6}
  7 |      3 | {1,3,7}
  2 | (null) | {2}
  4 |      2 | {2,4}
  8 |      2 | {2,8}
(8 rows)

Read about recursive queries.