psql 9.1错误:列必须出现在GROUP BY子句中或在聚合函数中使用

时间:2018-10-07 03:31:20

标签: arrays group-by integer postgresql-9.1 string-aggregation

我有3个表:摘要,段,人。

 people

      Column      |            Type             |                     
------------------+-----------------------------+
 id               | bigint                      |
 last_name        | character varying           | 
 middle_name      | character varying           | 
 first_name       | character varying           | 
 current_position | character varying           | 

 summaries

     Column     |            Type             |                       
----------------+-----------------------------+
 id             | bigint                      | 
 channel        | character varying           | 
 show           | character varying           | 
 seg_ids        | character varying           | segment ids
 date           | timestamp without time zone | 
 start_time     | timestamp without time zone | 
 end_time       | timestamp without time zone | 

segments

       Column       |            Type             |                                     
--------------------+-----------------------------+
 id                 | bigint                      | 
 block_id           | integer                     | 
 person_id          | bigint                      | foreign key (FK)
 person_role        | character varying           | 
 summ               | integer                     | summary id FK
 deleted            | boolean                     |    

我的表摘要中有一列seg_ids(段ID),它是一个整数字符串,通过此查询,我可以将其转换为整数数组,并返回一千个ID:

select regexp_split_to_array((select rtrim(ltrim(replace((select string_agg(seg_ids, ', ')), '], [', ', '), '['),']') from summaries where date between '2018-07-04' and '2018-07-06'),',')::int[];

现在具有该整数数组(seg_ids),我想使用它来显示所有摘要以及连接到这些细分的人员。我尝试此查询失败:

SELECT summ, block_id, person, seg.id as segid, su.channel, su.show, date::timestamp::date as shdate, "time"(su.start_time) as shst, CONCAT (ppl.last_name, ', ', ppl.first_name) AS full_name, substr(person_role, 1, 2) as person_role 
FROM segments seg    
LEFT JOIN summaries su on seg.summ = su.id    
LEFT JOIN people ppl  on ppl.id = person_id    
HAVING seg.id::int = any (  
   regexp_split_to_array((    
      SELECT   
         rtrim(ltrim(  
             replace(   
                string_agg(seg_ids, ', ')   
             , '], [', ', ')  
        , '['),']')    
      FROM summaries    
      WHERE date between '2018-07-04' and '2018-07-06')   
   ,',')::int[])  order by shdate, channel, shst, show, su.id, block_id, person,seg.id asc;

这给了我这个错误:

ERROR:  column "seg.summ" must appear in the GROUP BY clause or be used in an aggregate function   

我不想按结果分组,因为我给我的行比预期的要少。如何重写查询,这样我就不必按结果分组?

更新
人在细分表中。

SELECT summ,
   block_id,
   person,
   seg.id as segid, 
   su.channel, su.show,
   date::TIMESTAMP::date AS shdate,
   "time"(su.start_time) AS shst,
   "time"(su.end_time) AS shet,
   regexp_split_to_array(rtrim(ltrim(su.seg_ids, '['), ']'), ',')::int[] AS seg_id_int_arr,
   CONCAT (ppl.last_name, ', ', ppl.first_name) AS full_name,
   substr(person_role, 1, 2) AS person_role
FROM summaries su
LEFT JOIN segments seg ON seg.summ = su.id
LEFT JOIN people ppl ON ppl.id = person_id
WHERE date BETWEEN '2018-07-04' AND '2018-07-06'
 AND seg.id::int = ANY (regexp_split_to_array(rtrim(ltrim(seg_ids, '['), ']'), ',')::int[])
ORDER BY shdate, channel, shst, show, su.id, block_id, person, seg.id ASC;

1 个答案:

答案 0 :(得分:1)

您做错了一些基本的事情

  1. 您应该知道何时使用having / where子句。 where子句用于在执行聚合之前过滤行(可以使用group by或其他聚合函数)。而Haven子句用于在执行聚合后过滤数据。您可以参考此explanation
  2. 我看到段表已经具有摘要和人员ID的ID,因此可以通过join简化您要在Have子句中实现的最后一个条件。据我了解,您希望所有汇总信息都位于特定日期范围内的细分市场信息,这可以通过简单地改善我们的加入条件来实现,例如

    FROM segments seg    
    JOIN summaries su on seg.summ = su.id  
    AND su.date between '2018-07-04' and '2018-07-0`6'`
    LEFT JOIN people ppl on ppl.id = person_id
    
  3. 我还看到您选择了一个名为person的列,但在您的任何表中都看不到它