psql 9.1 ОШИБКА: столбец должен появляться в предложении GROUP BY или использоваться в статистической функции - PullRequest
0 голосов
/ 07 октября 2018

У меня есть 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 (сегменты идентификаторов), представляющий собой целочисленную строку, которую я смог преобразовать в массив целых чисел с помощью этого запроса, который возвращает более тысячи идентификаторов:

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   

Я не хочу группировать по результату, так как я бы дал меньше строк, чем ожидалось,Как я могу переписать запрос, чтобы мне не пришлось группировать по результату?

update
person находится в таблице сегментов.

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 голосов
/ 08 октября 2018

Вы делаете некоторые базовые вещи неправильно

  1. Вы должны знать, когда следует использовать пункт / где.Где предложение используется для фильтрации строк перед выполнением агрегации (это может быть использование group by или других функций агрегации).Принимая во внимание, что пункт Имеющий используется для фильтрации данных после агрегирования.Вы можете обратиться к этому объяснению
  2. Я вижу, что таблица сегментов уже имеет идентификатор для сводок и идентификатор человека, поэтому последнее условие, которое вы пытаетесь выполнить, имея условиеупрощено с объединениями.Из того, что я понимаю, вам нужна вся информация о сегментах, где сводка находится в определенном диапазоне дат, это можно сделать, просто улучшив наше условие соединения, например

    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. Также я вижу, что вы выбраликолонка с именем человека, но я не вижу его ни в одной из ваших таблиц

...