Postgres 按空字符串问题分组以在输出中包含空字符串

Postgres group by empty string question to include empty string in output

我在 Postgres

中关注 table
| 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 都需要此输出,其中缺少组的空字符串。

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

您可以使用条件聚合:

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

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

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

您需要 CTE returns phonegroup 的所有可能组合以及 left join 到 table 这样您可以 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,''     |