Проверьте, существует ли хотя бы один b для каждого a, где каждый b имеет ссылку внешнего ключа на a - PullRequest
0 голосов
/ 29 октября 2018

Допустим, у вас есть таблица a и таблица b, где каждый b имеет ссылку внешнего ключа на таблицу a. Как бы вы написали оператор SQL, отвечающий на вопрос, существует ли хотя бы один b для каждого a?

Чтобы оценить: скажем, у вас есть таблица пользователей:

create table users (
  id           bigserial  primary key,
  name         text
);

и таблица шляп, которые носят эти пользователи:

create table hats (
  id           bigserial  primary key,
  user_id      bigserial  references users,
  description  text
);

Как бы вы написали запрос, отвечающий на вопрос, есть ли у каждого пользователя хотя бы одна шапка, или перефразировать: есть ли пользователь без шапки?

Ответы [ 2 ]

0 голосов
/ 29 октября 2018

RhodiumToad на # postgresql @ freenode ответил:

Хотите результат как (user_id, has_hat)? Или просто список пользователей с шляпами или пользователей без шляп? Или один истинный / ложный результат для «У кого-нибудь есть шляпа?»

Наиболее эффективным ответом на различные вопросы будет ответ на первый вопрос:

select exists(
  select 1
    from users u
    where not exists(
      select 1
        from hats h
        where h.user_id=u.id));

Это потому, что (а) это можно планировать как анти-объединение и (б) останавливается в первом матче. Есть еще одно преимущество: буквально говорится: «существует ли пользователь таким, что для него нет шляпы», так что это должно быть легко понять будущим читателям.

Следующим лучшим вариантом, если вы хотите больше подробностей, является средний вариант (пользователи с / без шляп), например: - показывает всех пользователей хотя бы с одной шляпой Выбрать * от пользователей где существует ( выберите 1 из шапки ч где h.user_id = u.id);

-- shows all users with no hat
select *
    from users u
    where not exists(
      select 1
        from hats h
        where h.user_id=u.id);  

Первый вариант не так эффективен, поэтому его следует избегать:

-- shows all users, with a flag for whether they have a hat
select u.id, exists(
      select 1
        from hats h
        where h.user_id=u.id) as has_hat
    from users u; 
0 голосов
/ 29 октября 2018

Вы можете использовать LEFT JOIN для поиска пользователей без шляпы:

SELECT u.*
FROM users u
LEFT JOIN hats h
  ON u.id = h.user_id
WHERE h.user_id IS NULL;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...