将不同的行值组合成一个字符串-sql

时间:2017-09-06 17:43:22

标签: sql postgresql distinct string-aggregation

我想在每一行中取细胞并将它们变成一串名字......我的方法已经处理了套管。

例如,表格;

'john' |        | 'smith' | 'smith'    
'john' | 'paul' |         | 'smith'
'john' | 'john' | 'john'  |    

返回:

'john smith'
'john paul smith'
'john'

这需要运行postgres的postgreSQL 8.2.15,所以我不能使用像CONCAT这样的潜在有用函数,而且数据在greenplum db中。

或者,直接删除字符串列表中的重复令牌的方法可以让我实现更大的目标。例如:

'john smith john smith'
'john john smith'
'smith john smith'

返回

'john smith'
'john smith'
'smith john'

令牌的顺序并不重要,只要返回所有唯一值,只返回一次。

谢谢

3 个答案:

答案 0 :(得分:2)

规范化表结构,从该表中选择不同的名称值,创建一个聚合字符串的函数(参见,例如How to concatenate strings of a string field in a PostgreSQL 'group by' query?),然后应用该函数。除了集合函数创建之外,这可以在单个语句或视图中完成。

答案 1 :(得分:0)

我会通过取消数据然后重新聚合来做到这一点:

select id, string_agg(distinct col)
from (select id, col1 from t union all
      select id, col2 from t union all
      select id, col3 from t union all
      select id, col4 from t
     ) t
where col is not null
group by id;

这假设每行都有唯一的ID。

您还可以使用巨人case

select concat_ws(',',
                 col1,
                 (case when col2 <> col1 then col2 end),
                 (case when col3 <> col2 and col3 <> col1 then col3 end),
                 (case when col4 <> col3 and col4 <> col2 and col4 <> col1 then col4 end)
                ) as newcol
from t;

在Postgres的古老版本中,您可以将其标记为:

select trim(leading ',' from
            (coalesce(',' || col1, '') ||
             (case when col2 <> col1 then ',' || col2 else '' end) ||
             (case when col3 <> col2 and col3 <> col1 then ',' || col3 else '' end),
             (case when col4 <> col3 and col4 <> col2 and col4 <> col1 then ',' || col4 else '' end)
            )
           ) as newcol
from t;

答案 2 :(得分:0)

我为你找到了解决方案! :)

以下查询返回四列(我将其命名为col_1,2,3和4)并通过将test_table与自身连接来删除重复项。

以下是代码:

SELECT t1.col_1, t2.col_2, t3.col_3, t4.col_4

FROM (
    SELECT id, col_1
        FROM test_table
) AS t1

LEFT JOIN (
    SELECT id, col_2
        FROM test_table
) as t2

ON (t2.id = t1.id and t2.col_2 <> t1.col_1)


LEFT JOIN (
    SELECT id, col_3
        FROM test_table
) as t3

ON (t3.id = t1.id and t3.col_3 <> t1.col_1 and t3.col_3 <> t2.col_2)



LEFT JOIN (
    SELECT id, col_4
        FROM test_table
) as t4

ON (t4.id = t1.id and t4.col_4 <> t1.col_1 and t4.col_4 <> t2.col_2 and t4.col_4 <> t3.col_3);

如果要获取最终字符串,只需将“SELECT”行替换为以下字符串:

SELECT trim(both ' ' FROM  (COALESCE(t1.col_1, '') || ' ' ||  COALESCE(t2.col_2, '') || ' ' || COALESCE(t3.col_3, '') || ' ' || COALESCE(t4.col_4, '')))
根据文档:

,这应该与你的postgres版本一起使用

[用于修剪和连接功能]

https://www.postgresql.org/docs/8.2/static/functions-string.html

// *********** ******

[用于合并功能]

https://www.postgresql.org/docs/8.2/static/functions-conditional.html

如果我得到了帮助,请告诉我。)

P.S。您的问题听起来像是一个糟糕的数据库设计:我会将这些列移到一个表上,您可以通过使用group by或类似的东西来执行此操作。此外,我会在单独的脚本上进行字符串连接。 但这是我的做法:)