#sql #postgresql
#sql #postgresql
Вопрос:
Мой запрос
select link.id, bti_status.bti_status from link
inner join bti
on link.id = bti.id
inner join bti_status
on bti.id = bti_status.bti_id
возвращает следующую таблицу.
Я хотел бы, чтобы этот запрос возвращал только набор идентификаторов, у которых нет bti_status = 4, поэтому ни в одной из строк не должно быть возвращено id = 403, поскольку строка 5 имеет значение bti_status, равное 4.
Я пробовал следующий запрос, но я не уверен, правильно ли он выполняет работу.
select link.id, bti_status.bti_status from link
inner join bti
on link.id = bti.id
inner join bti_status
on bti.id = bti_status.bti_id
where not exists (select bti_status from bti_status where bti_status = 4);
Обновить
Что касается ответа @GMB, мой исходный запрос на самом деле отличается от того, который я опубликовал. Исходный запрос
select link.id, bti_status.bti_status, bti.id from link
inner join bti_link
on link.id = bti_link.id
inner join bti
on bti_link.bti_id = bti.id
inner join deadline
on deadline.id = link.deadline_id
inner join bti_status
on bti.id = bti_status.bti_id
where deadline.id = :id
and not exists (select bti_status from bti_status where bti_status = 4);
и если я попробую ваше решение, я не смогу заставить его работать
select l.id, bs.bti_status, b.id
from (
select l.id, bs.bti_status, b.id,
bool_or(bs.bti_status = 4) over(partition by l.id) has_status_4
from link l
inner join bti_link on l.id = bti_link.id
inner join bti b on bti_link.bti_id = b.id
inner join deadline d on d.id = l.deadline_id
inner join bti_status bs on b.id = bs.bti_id
) t
where d.id = :id
and not has_status_4;
Ответ №1:
как сказал GMB, функция window — это один из способов.
вы также можете использовать CTE:
WITH data AS (
SELECT link.id AS link_id, bti_status.bti_status, bti.id AS bti_id
FROM link
INNER JOIN bti_link ON link.id = bti_link.id
INNER JOIN bti ON bti_link.bti_id = bti.id
INNER JOIN deadline ON deadline.id = link.deadline_id
INNER JOIN bti_status ON bti.id = bti_status.bti_id
WHERE deadline.id = :id
)
SELECT *
FROM data
WHERE link_id NOT IN (
SELECT link_id
FROM data
WHERE bti_status = 4)
Комментарии:
1. Я не могу заставить его работать. я получаю сообщение об ошибке «Ошибка SQL [42702]: ОШИБКА: ссылка на столбец «id» неоднозначна Позиция: 376 ОШИБКА: ссылка на столбец «id» неоднозначна Позиция: 376 ОШИБКА: ссылка на столбец «id» неоднозначна Позиция: 376 »
2. Я отредактировал имена столбцов. попробуйте сейчас. в исходном запросе было два столбца с именем id .
Ответ №2:
Вы можете сделать это с помощью оконных функций. Вот один из способов сделать это с помощью логической агрегации окон:
select id, bti_status
from (
select l.id, bs.bti_status,
bool_or(bs.bti_status = 4) over(partition by l.id) has_status_4
from link l
inner join bti b on l.id = b.id
inner join bti_status bs on b.id = bs.bti_id
) t
where not has_status_4
Комментарии:
1. @Marko: удалите префиксы
l
,bs
иd
во внешнемselect
предложении (или используйтеt
везде): они не определены в этой области. Итак:select id, bti_status from (...) t where id = :id and not has_status_4
. Кроме того, у вас есть два столбца, вызываемыхid
в подзапросе, это неоднозначно. Вам нужно указать псевдоним хотя бы одного из них.2. Когда я это делаю, я получаю «Ошибка SQL [42P01]: ОШИБКА: отсутствует запись в предложении для таблицы «link» Позиция: 8 ОШИБКА: отсутствует запись в предложении для таблицы «link» Позиция: 8 ОШИБКА: отсутствует запись в предложении для таблицы «link» Позиция: 8 ОШИБКА: отсутствует запись в предложении для таблицы «link» Позиция: 8 »