Отношение один ко многим - возвращаются только результаты, в которых ВСЕ строки в связанной таблице соответствуют определенному критерию без использования коррелированного подзапроса. - PullRequest
0 голосов
/ 12 ноября 2010

У меня есть следующие таблицы:

  • заказ
  • сообщение: содержит столбец order_id, который является внешним ключом к таблице заказов
  • обзор: отслеживает, какие пользователи просмотрели заказ, содержит столбец order_id, который является внешним ключом для таблицы заказов, и идентификатор user_id, который является внешним ключом для таблицы пользователя
  • пользователь: отслеживает пользователя в системе, который может иметь или не иметь назначенную роль; содержит столбец role_id, который является внешним ключом таблицы ролей
  • роль: отслеживает особую роль для данного пользователя

Сообщение относится к заказу, и его могут просматривать многие пользователи. Каждому пользователю может быть назначена или не назначена особая роль. Я хочу вернуть только те сообщения, которые не были просмотрены ЛЮБЫМИ пользователями, которым была назначена специальная роль. Я написал запрос для этого, который опирается на коррелированный подзапрос (внутренний SELECT ссылается на message.order_id из внешнего SELECT). Это допустимо в T-SQL, но очень медленно.

Какой способ написания запроса более эффективен?

select message.id
  from message, order
  where order.id = message.order_id
  and not exists (select *
                    from user, review
                    where user.role_id is not null and
                          user.id = review.user_id and
                          review.order_id = message.order_id)

Ответы [ 4 ]

1 голос
/ 12 ноября 2010
select id 
 from message 
where id not in(
    select message.id
     from message
    inner join review
       on review.order_id = message.order_id
    inner join user
       on user.user_id = review.user_id
    where user.role_id is not null)

В предложении where я отбрасываю все сообщения, от которых есть рецензия, с назначенной ролью.И я думаю, что порядок таблицы в этом запросе не нужен

1 голос
/ 12 ноября 2010

Еще один взгляд на это:

SELECT message.id
  FROM message
INNER JOIN ORDER
  ON (order.id = message.order_id)
LEFT OUTER JOIN review
  ON (review.order_id = message.order_id)
LEFT OUTER JOIN user
  ON (user.id = review.user_id)
WHERE review.order_id IS NOT NULL AND
      user.role_id IS NULL;

Поделитесь и наслаждайтесь.

1 голос
/ 12 ноября 2010

Сделайте это и дайте мне знать, что вы думаете:

select * from message where id not in (

    select m.id
    from message m
    join order o on m.order_id = o.order_id
    join review r on o.order_id = r.order_id
    join user u on r.user_id = u.user_id
                and u.role_id is not null

)
0 голосов
/ 12 ноября 2010

Ваш существующий запрос довольно хорош, но объединение заказов не требуется - попробуйте:

select message.id
  from message
  where not exists (select null
                    from user, review
                    where user.role_id is not null and
                          user.id = review.user_id and
                          review.order_id = message.order_id)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...