SQL: Выберите записи, где ВСЕ записи, к которым присоединяются, удовлетворяют некоторое условие

Как я могу записать SQL-запрос, который возвращает запись, только если ВСЕ связанные записи в объединяемой таблице удовлетворяют некоторое условие.

Например, если A имеет много B, я хочу ВЫБРАТЬ * ИЗ, ГДЕ все имели отношение, B для данного A имеют B.some_val> значение

Я знаю, что это - вероятно, довольно основной вопрос, так спасибо за любую справку. Кроме того, если это имеет значение, я использую пост-ГРЭС.

Sam

7
задан sgriffinusa 26 July 2010 в 19:11
поделиться

6 ответов

Предполагая, что корреляция не нужна, используйте:

SELECT a.*
  FROM A a
 WHERE EXISTS(SELECT NULL
                FROM B b
              HAVING MIN(b.some_val) > a.val)

Если корреляция нужна:

SELECT a.*
  FROM A a
 WHERE EXISTS(SELECT NULL
                FROM B b
               WHERE b.id = a.id
              HAVING MIN(b.some_val) > a.val)

Объяснение

EXISTS оценивается по булеву числу, основанному на первом совпадении - это делает его быстрее, чем, скажем, использование IN, и - в отличие от использования JOIN - не будет дублировать строки. Часть SELECT не имеет значения - вы можете изменить ее на EXISTS SELECT 1/0 ... , и запрос все равно будет работать, хотя и будет очевидная ошибка деления на ноль.

Подзапрос внутри EXISTS использует агрегатную функцию MIN для получения наименьшего значения B.some_val - если это значение больше значения a.val, то a.val меньше всех значений b. Пункт WHERE нужен только для корреляции - агрегатные функции можно использовать только в пункте HAVING.

5
ответ дан 7 December 2019 в 07:39
поделиться
select * from A
 where -- at least one record in B is greater than some_val
       exists (select null from B
                where B.some_val > :value
                  and A.join_column = B.join_column)
   and -- no records in B are not greater than some_val
       not exists (select null from B
                    where B.some_val <= :value
                      and A.join_column = B.join_column)
2
ответ дан 7 December 2019 в 07:39
поделиться

Следующее должно работать:

SELECT *
FROM a
JOIN b ON a.key = b.key AND a.value > b.value

Поскольку это выполняет внутреннее соединение , а не внешнее соединение , записи из A будут только будут включены, если у них есть записи в B, удовлетворяющие условию.

Я не использую PostGRE, поэтому не могу гарантировать, что синтаксис в точности правильный.

0
ответ дан 7 December 2019 в 07:39
поделиться

Вам нужно ВНУТРЕННЕЕ СОЕДИНЕНИЕ:

SELECT
    A.*
FROM
    A
INNER JOIN B
    ON A.identifier = B.identifier
WHERE
    B.some_val > value

Вы захотите убедиться, что существует внешний ключ от A до B или какой-либо другой общий идентификатор.

0
ответ дан 7 December 2019 в 07:39
поделиться
select * from a where a.key = b.a_key where b.value > condition
0
ответ дан 7 December 2019 в 07:39
поделиться

Используйте книжные магазины и книги в качестве примера.

Книжный магазин

bookstoreID, bookID

Book

bookID, цена

Я полагаю, вы хотите вернуть все книжные магазины, в которых все книги имеют цену выше X.

select *
from Bookstore bs1
where bs1.bookstoreID not exist
 (
  select bs.bookstoreID
  from Bookstore bs, Book b
  where bs.bookID= b.bookID
  b.price < x;   -- your value                                                     
 )
0
ответ дан 7 December 2019 в 07:39
поделиться
Другие вопросы по тегам:

Похожие вопросы: