【问题标题】:Postgres group by empty string question to include empty string in outputPostgres 按空字符串问题分组以在输出中包含空字符串
【发布时间】:2019-08-10 17:47:53
【问题描述】:

我在 Postgres 中有下表

| phone | group   | spec   |
| 1     | 1       | 'Lock' |
| 1     | 2       | 'Full' |
| 1     | 3       | 'Face' | 
| 2     | 1       | 'Lock' | 
| 2     | 3       | 'Face' | 
| 3     | 2       | 'Scan' | 

试过了

SELECT phone, string_agg(spec, ', ')
FROM mytable
GROUP BY phone;

对于缺少组的空字符串的每个电话都需要此输出。

| phone | spec 
| 1     | Lock, Full, Face
| 2     | Lock, '' , Face
| 3     | '', Scan ,''

【问题讨论】:

  • 为什么列表中有 3 个成员代表 4 个不同的值?
  • 因为有三个不同的组,电话 2 没有组 '2' 值,电话 3 没有组 '1' 和 '3'

标签: sql postgresql string-aggregation


【解决方案1】:

您需要一个CTE,它将phonegroupleft join 的所有可能组合返回到表中,以便您可以group by phone

with cte as (
  select * 
  from (
    select distinct phone from mytable   
  ) m cross join (
    select distinct "group" from mytable  
  ) g 
)  
select c.phone, string_agg(coalesce(t.spec, ''''''), ',') spec
from cte c left join mytable t
on t.phone = c.phone and t."group" = c."group"
group by c.phone

请参阅demo
结果:

| phone | spec           |
| ----- | -------------- |
| 1     | Lock,Full,Face |
| 2     | Lock,'',Face   |
| 3     | '',Scan,''     |

【讨论】:

    【解决方案2】:

    您可以使用条件聚合:

    select phone,
           (max(case when group = 1 then spec else '''''' end) || ', ' ||
            max(case when group = 2 then spec else '''''' end) || ', ' ||
            max(case when group = 3 then spec else '''''' end) 
           ) as specs
    from mytable t
    group by phone;
    

    或者,您可以使用generate_series() 概括所有组,然后聚合:

    select p.phone,
           string_agg(coalesce(t.spec, ''''''), ', ') as specs
    from (select distinct phone from mytable) p cross join
         generate_series(1, 3, 1) gs(grp) left join
         mytable t
         on t.phone = p.phone and t.group = gs.grp
    group by p.phone
    

    【讨论】:

      【解决方案3】:

      您可以考虑将self - (RIGHT/LEFT)JOIN 与所有三个不同的组(在子查询中紧随RIGHT JOIN 关键字之后说明)和表的相关查询一起使用:

      WITH mytable1 AS
      (
      SELECT distinct t1.phone, t2."group", 
            ( SELECT spec FROM mytable WHERE phone = t1.phone AND "group"=t2."group" )
        FROM mytable t1
        RIGHT JOIN ( SELECT distinct "group" FROM mytable ) t2
          ON t2."group" = coalesce(t2."group",t1."group")
      )
      SELECT phone, string_agg(coalesce(spec,''''''), ', ') as spec
        FROM mytable1
       GROUP BY phone;
      

      Demo

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-12-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-05-02
        • 2012-08-08
        相关资源
        最近更新 更多