限制在Postgres中的string_agg按顺序排序

huangapple go评论53阅读模式
英文:

Restrict string_agg order by in postgres

问题

在使用PostgreSQL数据库时,我遇到了一个情况,需要根据存储在表中的逗号分隔的字段ID来显示列名。以下是一个示例:

表1名称:labelprint

id field_id
1  1,2

表2名称:datafields

id field_name
1  年龄
2  姓名
3  性别

为了根据从table1中提取的字段ID(即field_id列中的1,2)来显示字段名,我希望字段名按其相应的ID的顺序显示如下:

期望结果:

id field_id field_name
1  2,1      姓名,年龄

为了实现上述结果,我编写了以下查询:

select l.id,l.field_id ,string_agg(d.field_name,',') as field_names
from labelprint l
join datafields d on d.id = ANY(string_to_array(l.field_id::text,','))
group by l.id
order by l.id

然而,string_agg()函数会按升序对最终字符串进行排序,并显示以下输出:

id field_id field_name
1  2,1      年龄,姓名

正如您所见,字段名列中的顺序未按照field_id值的顺序显示,这是我希望按照field_id值的顺序显示的。

非常感谢您提前的任何建议/帮助!

英文:

While working with postgres db, I came across a situation where I will have to display column names based on their ids stored in a table with comma separated. Here is a sample:

table1 name: labelprint

id field_id
1  1,2

table2 name: datafields

id field_name
1  Age
2  Name
3  Sex

Now in order to display the field name by picking ids from table1 i.e. 1,2 from field_id column, I want the field_name to be displayed in same order as their respective ids as

Expected result:

id field_id field_name
1  2,1      Name,Age

To achieve the above result, I have written the following query:

select l.id,l.field_id ,string_agg(d.field_name,',') as field_names
from labelprint l
join datafields d on d.id = ANY(string_to_array(l.field_id::text,','))
group by l.id
order by l.id

However, the string_agg() functions sort the final string in ascending order and displays the output as shown below:

id field_id field_name
1  2,1      Age, Name

As you can see the order is not maintained in the field_name column which I want to display as per field_id value order.

Any suggestion/help is highly appreciated.

Thanks in advance!

Already mentioned in the description.

答案1

得分: 1

虽然这样可能会对性能、可读性和可维护性造成严重影响,但你可以动态计算你想要的顺序:

    select l.id,l.field_id,
      string_agg(d.field_name,',' 
        order by array_position(string_to_array(l.field_id::text,','),d.id)
      ) as field_names
    from labelprint l
    join datafields d on d.id = ANY(string_to_array(l.field_id::text,','))
    group by l.id
    order by l.id;

至少你应该将数组实际存储为实际的数组,而不是存储为逗号分隔的字符串。或者使用中间表,根本不要存储数组。
英文:

While this will probably be horrible for performance, as well as readability and maintainability, you can dynamically compute the order you want:

select l.id,l.field_id,
  string_agg(d.field_name,',' 
    order by array_position(string_to_array(l.field_id::text,','),d.id)
  ) as field_names
from labelprint l
join datafields d on d.id = ANY(string_to_array(l.field_id::text,','))
group by l.id
order by l.id;

You should at least store your array as an actual array, not as a comma delimited string. Or maybe use an intermediate table and don't store arrays at all.

答案2

得分: -1

使用对现有查询的轻微修改,您可以按如下方式执行它:

select l.id, l.field_id, string_agg(d.field_name, ',') as field_names
from labelprint l
join datafields d on d.id::varchar = ANY(string_to_array(l.field_id, ','))
group by l.id, l.field_id
order by l.id

演示在此处

英文:

With a small modification to your existing query you could do it as follows :

select l.id, l.field_id, string_agg(d.field_name,',') as field_names
from labelprint l
join datafields d on d.id::varchar = ANY(string_to_array(l.field_id,','))
group by l.id, l.field_id
order by l.id

Demo here

huangapple
  • 本文由 发表于 2023年2月14日 21:01:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/75448229.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定