У меня есть следующий выбор:
SELECT
posm.id AS org_scope_metric_id,
cc.code AS control_code,
ccp.code AS part_code,
pop.id AS program_id
FROM public.org_scope_metric posm
JOIN public.org_metric pom ON pom.id = posm.metric_id
JOIN compliance.metric cm ON cm.id = pom.metric_id
JOIN compliance.control_part_metric ccpm ON ccpm.metric_id = cm.id
JOIN compliance.control_part ccp ON ccp.id = ccpm.part_id
JOIN compliance.control cc ON cc.id = ccp.control_id
JOIN compliance.program_framework cpf ON cpf.framework_id = cc.framework_id
JOIN public.org_program pop ON pop.program_id = cpf.program_id
WHERE posm.scope_id ='e6d11bfe-e5fc-11ee-8cda-238cdb93d281'
GROUP BY posm.id, cc.code, ccp.code, pop.id
который возвращает такой результат:
Если есть org_scope_metric_ids с разными program_id, мне нужно пропустить их все из выбора.
Пожалуйста, помогите решить проблему!
Пожалуйста, всегда включайте минимально воспроизводимый пример . То есть как исходные данные примера, так и желаемые результаты для этих данных примера. Почему я должен предоставлять минимальный воспроизводимый пример для очень простого SQL-запроса?


Подсчитайте количество одинаковых вхождений org_scope_metric_id и количество различных program_id-ов в каждой группе, а затем отфильтруйте строки результатов, в которых оба числа больше 1.
with t as (
select *,
count(*) over w cnt,
array_agg(program_id) over w program_id_list
from (<your query here>) t
window w as (partition by org_scope_metric_id)
)
select * from t
where cnt > 1 and array_distinct_count(program_id_list) > 1;
Для этого вам понадобится вспомогательная функция -
create or replace function array_distinct_count(arr anyarray)
returns integer language sql immutable as $$
select count(distinct el) from unnest(arr) el;
$$;
Я получаю ошибку DISTINCT is not implemented for window functions :(
Ой, пропустил это. Ответ обновлен.
Вы можете использовать оконные функции min и max.
SELECT *
FROM (
SELECT
posm.id AS org_scope_metric_id,
cc.code AS control_code,
ccp.code AS part_code,
pop.id AS program_id,
MIN(pop.id) OVER (PARTITION BY posm.id) = MAX(pop.id) OVER (PARTITION BY posm.id) AS all_same_id
FROM public.org_scope_metric posm
JOIN public.org_metric pom ON pom.id = posm.metric_id
JOIN compliance.metric cm ON cm.id = pom.metric_id
JOIN compliance.control_part_metric ccpm ON ccpm.metric_id = cm.id
JOIN compliance.control_part ccp ON ccp.id = ccpm.part_id
JOIN compliance.control cc ON cc.id = ccp.control_id
JOIN compliance.program_framework cpf ON cpf.framework_id = cc.framework_id
JOIN public.org_program pop ON pop.program_id = cpf.program_id
WHERE posm.scope_id ='e6d11bfe-e5fc-11ee-8cda-238cdb93d281'
GROUP BY posm.id, cc.code, ccp.code, pop.id
) p
WHERE all_same_id;
Почему бы не переместить MIN(pop.id) OVER (PARTITION BY posm.id) = MAX(pop.id) OVER (PARTITION BY posm.id) в предложение WHERE? и устранение необходимости в подзапросе?
Потому что вы не можете поместить оконные функции в WHERE, только в предложение QUALIFY, которое Postgres не поддерживает.
Большое вам спасибо, ребята. Мое окончательное решение в соответствии с вашими предложениями:
SELECT
org_scope_metric_id,
program_scope_id,
array_agg(program_scope_id) OVER (PARTITION BY org_scope_metric_id) AS metric_program_scopes
FROM (
<long_selection_from_the_question>
) subquery
GROUP BY subquery.org_scope_metric_id, subquery.program_scope_id
Итак, главное, что мне пришлось использовать OVER (PARTITION BY), чтобы получить необходимое количество.
не могли бы вы уточнить свой вопрос?