【问题标题】:Convert comma separated id to comma separated string in postgresql在postgresql中将逗号分隔的id转换为逗号分隔的字符串
【发布时间】:2018-09-15 14:42:45
【问题描述】:

我有逗号分隔的列,表示紧急类型的 id,例如:

ID | Name
1  | 1,2,3 
2  | 1,2
3  | 1

我想进行查询以获取此值字段的名称。

1 - Ambulance
2 - Fire
3 - Police

预期输出

1 - Ambulance, Fire, Police
2 - Ambulance, Fire
3 - Ambulance

我只需要在 postgresql 中编写 select 语句来显示字符串值,而不是用逗号分隔的整数值。

【问题讨论】:

    标签: postgresql


    【解决方案1】:

    逗号分隔值是不好的数据库设计实践,尽管 postgre 功能如此丰富,您可以轻松处理此任务。

    -- just simulate tables
    with t1(ID, Name) as(
        select 1  ,'1,2,3' union all
        select 2  ,'1,2' union all
        select 3  ,'1' 
    ),
    t2(id, name) as(
        select 1, 'Ambulance' union all
        select 2, 'Fire' union all
        select 3, 'Police' 
    )
    
    -- here is actual query
    select s1.id, string_agg(t2.name, ',') from 
    ( select id, unnest(string_to_array(Name, ','))::INT as name_id from t1 ) s1
    join t2
    on s1.name_id = t2.id
    group by s1.id
    

    demo

    不过,如果可以的话,改变你的方法。正确的数据库设计意味着简单的查询和更好的性能。

    【讨论】:

      【解决方案2】:

      要获取每个 id 的值是一个简单的查询:select * from ;。一旦你有了这些值,你就必须用分隔符','来解析字符串。那么您必须将解析的 sting 值分配给适当的职位,并重新制作列表。你是用特定的语言写的吗?

      或者您可以将排序后的值分配给诸如 1,2,3 等于“某个字符串”,1,2 等于“某个其他字符串”等。

      【讨论】:

        【解决方案3】:

        假设您有一个包含 Ambulance、Police 和 Fire 的 id 和值的表,那么您可以使用如下所示的内容。

        CREATE TABLE public.test1
        (
          id integer NOT NULL,
          commastring character varying,
          CONSTRAINT pk_test1 PRIMARY KEY (id)
        );
        
        INSERT INTO public.test1
        VALUES (1, '1,2,3'), (2, '1,2'), (3, '1');
        
        CREATE TABLE public.test2
        (
          id integer NOT NULL,
          description character varying,
          CONSTRAINT pk_test2 PRIMARY KEY (id)
        );
        
        INSERT INTO public.test2
        VALUES (1, 'Ambulance'), (2, 'Fire'), (3, 'Police');
        
        with descs as
        (with splits as 
        (SELECT id, split_part(commastring, ',', 1) as col2, 
        split_part(commastring, ',', 2) as col3, split_part(commastring, ',', 3) as col4 from test1)
        select splits.id, t21.description as d1, t22.description as d2, t23.description as d3
        from splits 
        inner join test2 t21 on t21.id::character varying = splits.col2
        left join test2 t22 on t22.id::character varying = splits.col3
        left join test2 t23 on t23.id::character varying = splits.col4)
        SELECT descs.id, CASE WHEN d2 IS NOT NULL AND d3 IS NOT NULL 
        THEN CONCAT_WS(',', d1,d2,d3) ELSE CASE WHEN d2 IS NOT NULL 
        THEN CONCAT_WS(',', d1,d2) ELSE d1 END END FROM descs
        ORDER BY id;
        

        作为解释,我给出了创建表和插入命令,以便您(和其他人)可以遵循逻辑。如果你在你的问题中这样做,这将非常有帮助,因为它可以节省每个人的时间并避免误解。

        然后我的内部 CTE 使用 split_part 拆分字符串。这里的语法很简单,字段、分隔符和要拆分的字段中的所需列(因此在这种情况下,我们需要一、二和三)。然后我将拆分列加入 test2。这里注意两点:第一个连接是内连接,因为拆分中总会有至少一列(我假设!!!),而另外两个是左连接;其次,字符变化字段的拆分反过来会产生字符变化拆分,因此我必须将 int id 转换为字符变化才能使连接起作用。以这种方式进行强制转换(即 id 到字符变化而不是字符变化到 id)意味着我不必为空值而烦恼。最后,根据存在的空值的数量,我将结果与给定的分隔符连接起来。我再次假设 d1 总是有一个值。

        HTH

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2016-02-08
          • 1970-01-01
          • 2018-08-16
          • 2013-09-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多