SQL,如何对具有优先约束的查询结果进行排序

时间:2018-07-31 07:15:47

标签: sql postgresql

我有两个关系为1-n的表。我正在寻找订购元素的方式。我可以使用列“ position(int)”,但我更喜欢使用优先级的ID:

+-------+---------------+-------+
| pk_id | precedence_id | fk_id |
+-------+---------------+-------+
|     4 |             1 |    10 |
+-------+---------------+-------+
|     1 |             6 |    10 |
+-------+---------------+-------+
|     2 |             5 |    40 |
+-------+---------------+-------+
|     3 |          NULL |    10 |
+-------+---------------+-------+
|     6 |             3 |    10 |
+-------+---------------+-------+
|     5 |          NULL |    40 |
+-------+---------------+-------+

我在同一张表上有一个主键(pk_id),一个外键(fk_id)和一个优先级约束(precedence_id)。

我正在寻找查询以获取具有优先级的结果:

+-------+---------------+-------+
| pk_id | precedence_id | fk_id |
+-------+---------------+-------+
|     3 |          NULL |    10 |
+-------+---------------+-------+
|     6 |             3 |    10 |
+-------+---------------+-------+
|     1 |             6 |    10 |
+-------+---------------+-------+
|     4 |             1 |    10 |
+-------+---------------+-------+
|     5 |          NULL |    40 |
+-------+---------------+-------+
|     2 |             5 |    40 |
+-------+---------------+-------+

SELECT * 
FROM tb 
ORDER BY fk_id, ??

3 个答案:

答案 0 :(得分:1)

这正常工作:

WITH RECURSIVE recursive(pk_id, precedence_id, position) AS (
    SELECT pk_id, precedence_id, 0
    FROM tb
    WHERE precedence_id ISNULL

    UNION ALL

    SELECT v.pk_id, v.precedence_id, rec.position + 1
    FROM
        tb v
        INNER JOIN recursive rec ON rec.pk_id = v.precedence_id
)
SELECT tst.*, rec.position
FROM
    recursive rec
    INNER JOIN tb tst ON rec.pk_id = tst.pk_id
ORDER BY tst.fk_id, rec.position;

答案 1 :(得分:0)

order by子句

中使用priority_id
select * from tb
order by fk_id,precedence_id desc,pk_id

http://sqlfiddle.com/#!17/ba4b8/5

答案 2 :(得分:0)

with  recursive t (pk_id,path,L_name) as (

 select  pk_id
        ,array[pk_id]
        ,coalesce(precedence_id,0) as L_tree -- can be representative relation_name 
        ,precedence_id
        ,fk_id
   from tb 
  where coalesce(precedence_id,0) = 0 

union all 

 select  el.pk_id
        ,t.path || array[el.pk_id]
        ,coalesce(el.precedence_id,0) as L_tree -- can be representative relation_name 
        ,coalesce(el.precedence_id,0) as precedence_id
        ,el.fk_id

   from tb as el 
   join t on (el.precedence_id= t.pk_id)
  where el.pk_id <> any (t.path))

 select pk_id
       ,cast(case when array_upper(path,1)>1 then '    ' else '' end || repeat('    ', array_upper(path,1)-2)||L_name  as character varying(1000)) as L_tree
       ,precedence_id
       ,array_upper(path,1) as tree_level
       ,fk_id  from t 

 order by path

尝试使用递归。 我是从我的一个旧项目中挖出来的。

编辑: 找到了类似的示例hierarchical data in postgres