保留 distinct 内部的顺序 string_agg

Preserve the order of distinct inside string_agg

我的SQL函数:

with recursive locpais as (
    select l.id, l.nome, l.tipo tid, lp.pai
    from loc l
    left join locpai lp on lp.loc = l.id
    where l.id = 12554
    union
    select l.id, l.nome, l.tipo tid, lp.pai
    from loc l
    left join locpai lp on lp.loc = l.id
    join locpais p on (l.id = p.pai)
)
select * from locpais

给我

12554 |     PARNA Pico da Neblina | 9 | 1564
12554 |     PARNA Pico da Neblina | 9 | 1547
 1547 |  São Gabriel da Cachoeira | 8 | 1400
 1564 | Santa Isabel do Rio Negro | 8 | 1400
 1400 |                 RIO NEGRO | 7 |  908
  908 |          NORTE AMAZONENSE | 6 |  234
  234 |                  Amazonas | 5 |  229
  229 |                     Norte | 4 |   30
   30 |                    Brasil | 3 |

这是地方的层次结构。 "PARNA" 代表 "National Park",这个涵盖两个城市:São Gabriel da Cachoeira 和 Santa Isabel do Rio Negro。因此它出现了两次。

如果我更改最后一行

select string_agg(nome,', ') from locpais

我明白了

"PARNA Pico da Neblina, PARNA Pico da Neblina, São Gabriel da Cachoeira, Santa Isabel do Rio Negro, RIO NEGRO, NORTE AMAZONENSE, Amazonas, Norte, Brasil"

这几乎没问题,除了双 "PARNA Pico da Neblina"。所以我尝试了:

select string_agg(distinct nome, ', ') from locpais

但现在我明白了

"Amazonas, Brasil, Norte, NORTE AMAZONENSE, PARNA Pico da Neblina, RIO NEGRO, Santa Isabel do Rio Negro, São Gabriel da Cachoeira"

这是错误的。我正在尝试在 string_agg 中添加一个 order by,但无法使其工作。表的定义给出了.

select string_agg(nome,', ')
from (
    select distinct nome
    from locpais
    order by tid desc
) s

如您所知,如果您不先按不同的表达式排序,则无法组合 DISTINCTORDER BY

但是可以使用

array_to_string(arry_uniq_stable(array_agg(nome ORDER BY tid DESC)), ', ') 

借助函数 arry_uniq_stable 删除数组中的重复项 w/o 改变它的顺序,就像我在

中给出的示例

请注意使用实际为您提供确定性结果的 ORDER BY 表达式。对于您给出的示例,仅 tid 是不够的,因为存在具有不同 nome.

的重复值 (8)