Как перечислить не существующие объекты?

заголовок мог бы немного сбивать с толку, позволить мне объяснить, ;) У меня есть 3 таблицы:

[names]
n_id;name
1;Jeff
2;Adam

[books]
b_id;title
1;Book1
2;Book2

[read]
n_id;b_id

Таблица [чтение] является таблицей с книгами чтения. если Adam читает "Book1", объект в [чтении] похож на это:

2;1

пока все хорошо. Теперь, есть ли способ знать, какие книги не были прочитаны человеком? Мы знаем, что только Adam прочитал книгу "Book1", таким образом, запрос должен произвести что-то вроде этого:

n_id;name;b_id;title
1;Jeff;1;Book1
1;Jeff;2;Book2
2;Adam;2;Book2

действительно ли возможно сделать это в 1 запросе, или мне нужны некоторые сценарии?

5
задан MilMike 3 March 2010 в 21:33
поделиться

4 ответа

Вы можете использовать CROSS JOIN для получения всех возможных комбинаций имен и книг, а затем использовать LEFT JOIN на read с IS NULL для удаления существующих там строк.

При LEFT JOIN возвращается NULL для всех объединенных столбцов, в которых нет строк, поэтому проверка, если r.n_id IS NULL, удаляет те строки, в которых объединение действительно нашло строки в read.

SELECT n.n_id, n.name, b.b_id, b.title
FROM names n
CROSS JOIN books b
LEFT JOIN read r ON ( r.n_id = n.n_id AND r.b_id = b.b_id )
WHERE r.n_id IS NULL
2
ответ дан 15 December 2019 в 00:58
поделиться

Вы бы сделали декартово соединение между именами и книгами, чтобы получить все возможные комбинации имени / книги, а затем минус те, которые были прочитаны:

SELECT n_id, b_id
FROM names, books
MINUS
SELECT n_id, b_id
FROM read

Другие предлагали выполнить перекрестное соединение и левое соединение, что также будет работать идеально. Возможно, вы захотите попробовать оба, чтобы увидеть, что быстрее в реальном сценарии - я подозреваю, что левое соединение, предложенное другими, будет быстрее, но не совсем уверен.

1
ответ дан 15 December 2019 в 00:58
поделиться

Ваш вопрос был: «Есть ли способ узнать, какие книги не читал человек ?» Но результаты вашего образца запроса показали ответ на вопрос: «Есть ли способ узнать, какие книги читали не все люди?»

Если вы действительно хотите просто выполнить запрос для конкретного человека, что-нибудь вот так должно работать:

SELECT b_id, title
FROM books  --You said you're just looking for books
WHERE b_id NOT IN
  (SELECT b_id
   FROM read
   WHERE n_id = @names_id) --pass in the names_id as a parameter
0
ответ дан 15 December 2019 в 00:58
поделиться

Вам необходимо перекрестное соединение, чтобы сгенерировать все пары имя vs книга , а затем соединить с прочтите таблицу и проверьте, где соединение не удалось.

SELECT names.n_id, names.name, books.b_id, books.title
FROM names
CROSS JOIN books 
LEFT JOIN read
ON names.n_id = read.n_id AND books.b_id = read.b_id
WHERE read.n_id IS NULL
1
ответ дан 15 December 2019 в 00:58
поделиться
Другие вопросы по тегам:

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