【问题标题】:Aggregate result of sub query to comma separated values将子查询的结果聚合为逗号分隔值
【发布时间】:2021-07-02 23:09:10
【问题描述】:

如何以逗号分隔值的形式获取子查询的结果。

我有三个表,locationstock_location_typelocation_label

我正在加入 location 和 stock_location_type 并且基于 SLT.inventory_location_cd 的结果,我正在查询另一个表 location_label

为此,我正在编写以下查询。

select L.stock_catalogue_id, SLT.inventory_location_cd,
       case
           when nventory_location_cd = 'base location' then  (select related_location_id from location_label where base_location_id = location_id)
           when nventory_location_cd != 'base location' then (select base_location_id from location_label where related_location_id = location_id)
           end as "Current Location",
       * from location L
join stock_location_type SLT on L.stock_location_type_id = SLT.stock_location_type_id;

这些子查询返回多行。

我尝试使用 string_agg 并转换 related_location_id 和 base_location_id(因为它们是 UUID)。但随后它抱怨 group by。

如果我使用 group by 那么它会出错,'multiple rows returned by subquery'

我错过了什么?

【问题讨论】:

    标签: postgresql join aggregate-functions


    【解决方案1】:

    您可以使用string_agg 函数来聚合逗号分隔字符串中的值。所以你的子查询需要重写为

    select string_agg(related_location_id, ', ') from location_label where base_location_id = location_id 
    

    select string_agg(base_location_id, ', ') from location_label where related_location_id = location_id 
    

    【讨论】:

      【解决方案2】:

      我用

      重新创建了你的表集

      location_label

      create table location_label(location_id int, location_label varchar);
      insert into location_label values(1, 'Home');
      insert into location_label values(2, 'Office');
      insert into location_label values(3, 'Garage');
      insert into location_label values(4, 'Bar');
      

      stock_location_type

      create table stock_location_type (stock_location_type_id int, inventory_location_cd varchar);
      insert into stock_location_type values(1, 'base location');
      insert into stock_location_type values(2, 'Not base location');
      

      location

      create table location (stock_catalogue_id int, base_location_id int, related_location_id int, stock_location_type_id int);
      
      insert into location values(1,1,2,1);
      insert into location values(1,2,1,2);
      insert into location values(1,3,3,1);
      
      insert into location values(2,4,3,1);
      insert into location values(2,3,1,1);
      insert into location values(2,2,4,2);
      

      如果我正确理解您的陈述,您将尝试使用base_location_idlocation_id 基于inventory_location_cd 列加入locationlocation_label 表。

      如果这是您想要实现的目标,那么下面的查询应该可以做到。通过将连接条件移动到适当的位置

      select L.stock_catalogue_id, 
       SLT.inventory_location_cd, 
       location_id "Current Location Id",
       location_label "Current Location Name"
      from location L join stock_location_type SLT 
      on L.stock_location_type_id = SLT.stock_location_type_id
      left outer join location_label 
      on (
        case when 
          inventory_location_cd = 'base location' 
        then base_location_id 
        else related_location_id 
        end) = location_id
      ;
      

      结果是

       stock_catalogue_id | inventory_location_cd | Current Location Id | Current Location Name 
      --------------------+-----------------------+---------------------+-----------------------
                        1 | base location         |                   1 | Home
                        1 | Not base location     |                   1 | Home
                        1 | base location         |                   3 | Garage
                        2 | base location         |                   3 | Garage
                        2 | base location         |                   4 | Bar
                        2 | Not base location     |                   4 | Bar
      (6 rows)
      

      如果您需要通过stock_catalogue_idinventory_location_cd 将其聚合起来,可以使用

      select L.stock_catalogue_id, 
       SLT.inventory_location_cd,
       string_agg(location_id::text, ',') "Current Location Id",
       string_agg(location_label::text, ',') "Current Location Name"
      from location L join stock_location_type SLT 
       on L.stock_location_type_id = SLT.stock_location_type_id
       left outer join location_label 
       on (case when inventory_location_cd = 'base location' then base_location_id else related_location_id end) = location_id
      group by L.stock_catalogue_id, 
       SLT.inventory_location_cd;
      

      结果是

       stock_catalogue_id | inventory_location_cd | Current Location Id | Current Location Name 
      --------------------+-----------------------+---------------------+-----------------------
                        1 | base location         | 1,3                 | Home,Garage
                        1 | Not base location     | 1                   | Home
                        2 | base location         | 3,4                 | Garage,Bar
                        2 | Not base location     | 4                   | Bar
      (4 rows)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-09-11
        • 2011-02-21
        • 1970-01-01
        • 2011-07-16
        • 2010-10-04
        • 2014-04-22
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多