PostgreSQL无法聚合来自多个表的数据

时间:2018-08-13 15:12:46

标签: sql postgresql

为简单起见,我将在表中写入最少数量的字段。 假设我有这个表:items,item_photos,item_characteristics。

create table items (
  id               bigserial primary key,
  title            jsonb                                   not null,
);
create table item_photos (
  id         bigserial primary key,
  path       varchar(1000)                not null,
  item_id    bigint references items (id) not null,
  sort_order smallint                     not null,
  unique (path, item_id)
);
create table items_characteristics (
  item_id                  bigint references items (id),
  characteristic_id        bigint references characteristics (id),
  characteristic_option_id bigint references characteristic_options (id),
  numeric_value            numeric(19, 2),
  primary key (item_id, characteristic_id),
  unique (item_id, characteristic_id, characteristic_option_id));

我想汇总一项的所有照片和特征。 首先,我明白了。

select i.id                                                                              as id,
       i.title                                                                           as title,

       array_agg( ip.path)                                 as photos,

       array_agg(
         array [ico.characteristic_id, ico.characteristic_option_id, ico.numeric_value]) as characteristics_array
FROM items i
       LEFT JOIN item_photos ip on i.id = ip.item_id
       LEFT JOIN items_characteristics ico on ico.item_id = i.id
GROUP BY i.id

这里的第一个问题是,如果item_characteristics中有4个与一个项目相关的条目,例如,item_photos没有条目,我将在photos字段{{ 1}}。 所以我不得不使用array_remove:

{null, null, null, null}

此外,如果我有1张照片和4张特征,则会得到4张照片的重复副本,例如:array_remove(array_agg(ip.path), null) as photos

所以我不得不使用不同的:

{img/test-img-1.png,img/test-img-1.png,img/test-img-1.png,img/test-img-1.png}

对我来说,这个决定很尴尬。 我不得不在item_characteristics中再添加2个字段,这使情况变得复杂:

array_remove(array_agg(distinct ip.path), null)                                   as photos,

array_agg(distinct
         array [ico.characteristic_id, ico.characteristic_option_id, ico.numeric_value]) as characteristics_array

所以我需要从item_characteristics中聚合5个值,其中2个已经是jsonb并且与众不同可能会对性能产生非常负面的影响。 还有更优雅的解决方案吗?

1 个答案:

答案 0 :(得分:1)

加入之前

SELECT i.id as id, i.title as title, ip.paths, null as photos,
       ico.characteristics_array
FROM items i LEFT JOIN
     (SELECT ip.item_id, array_agg( ip.path) as paths
      FROM item_photos ip
      GROUP BY ip.item_ID
     ) ip 
     ON ip.id = i.item_id LEFT JOIN
     (SELECT ico.item_id,
             array_agg(array [ico.characteristic_id, ico.characteristic_option_id, ico.numeric_value]
                       ) as characteristics_array
      FROM items_characteristics ico
      GROUP BY ico.item_id
     ) ico
     ON ico.item_id = i.id