SQL-запрос: объединение двух таблиц, в которых сущность первой таблицы отсутствует, или нескольких записей в другой таблице - PullRequest
0 голосов
/ 10 июня 2011

У меня есть таблицы базы данных, где сущности первой таблицы могут иметь или не иметь связанных записей во второй таблице:

Table 1          Table 2       
+-----+-----+    +-----+-------+-------+
| ID  | ... |    | ID  | T1_ID | NAME  |
+-----+-----+    +-----+-------+-------+
|  1  | ... |    |  1  |   1   |  p1   |
|  2  | ... |    |  2  |   1   |  p2   |
|  3  | ... |    |  3  |   2   |  p1   |
|  4  | ... |    +-----+-------+-------+
+-----+-----+

У меня есть следующие запросы, которые мне нужно выполнить:

  1. Получить все объекты таблицы_1 с определенной записью таблицы_2 - это просто, простое объединение сделает ...

  2. Получить все объекты таблицы_1, которыене связана конкретная запись Table_2 - не так просто, но мне также удалось запросить это с помощью объединения.

  3. Получить все объекты таблицы_1, которые имеют конкретную запись (A) и не имеет другой конкретной записи (B), связанной, т. Е. Получить все сущности Table_1, которые имеют сущность Table_2 с именем = p1 и не имеют сущности Table_2 с именем = p2, связанной.

Можно ли выполнить запрос типа (3) в одном выражении sql без подзапроса?

Ответы [ 4 ]

4 голосов
/ 10 июня 2011

Получить все объекты таблицы_1, которые иметь конкретную запись (А) и не есть другая конкретная запись (B) связаны, т.е. получают все объекты Table_1, которые имеют сущность Table_2 с именем = p1 и не имеет сущности таблицы_2 с именем = p2 связано.

У меня возникли проблемы с пониманием ваших критериев, но я думаю, что это то, что вы хотите:

SELECT * 
FROM Table1 t1 
JOIN Table2 t2 ON t1.ID = t2.t1_id 
WHERE t2.name = 'p1' 
AND NOT EXISTS(SELECT 'x' FROM Table2 t2_2 WHERE t1.ID = t2_2.t1_id AND t2_2.name = 'p2')

Это даст вам все из Таблицы 1, в которой есть совпадающая запись в Таблице 2 с именем = 'p1', и НЕ СУЩЕСТВУЕТ соответствующая запись в Таблице 2 с именем = 'p2'. Это то, что вам нужно?

ИЗМЕНИТЬ СНОВА:

Я подумал о более разумном способе сделать это, который включает статический (некоррелированный) подзапрос. Этот подзапрос будет выполняться только один раз, а не один раз для каждой родительской строки в таблице Table1. Я не проводил этот код через анализатор запросов, но он должен быть значительно быстрее, чем запросы, использующие EXISTS (...)

SELECT * 
FROM Table1 t1 
JOIN Table2 t2 ON t1.ID = t2.t1_id 
WHERE t2.name = 'p1' 
AND t1.id NOT IN(SELECT t1_id FROM Table2 WHERE name = 'p2')
3 голосов
/ 10 июня 2011

Вы можете использовать подзапрос EXISTS (фактически, аналогично выполнению двух объединений).

SELECT * FROM Table_1 AS t1
WHERE EXISTS (SELECT * FROM Table_2 AS t2 WHERE t1.Id = t2.Id AND Name='p1')
AND NOT EXISTS (SELECT * FROM Table_2 AS t2 WHERE t1.Id = t2.Id AND Name='p2')
0 голосов
/ 10 июня 2011

Чтобы сделать вариант решения более полным:

SELECT t1.*
FROM Table_1 t1
  INNER JOIN Table_2 it2 ON t1.ID = it2.T1_ID AND it2.NAME = 'p1'
  LEFT JOIN Table_2 lt2  ON t1.ID = lt2.T1_ID AND lt2.NAME = 'p2'
WHERE lt2.ID IS NULL
0 голосов
/ 10 июня 2011

Чтобы получить все вхождения, где t2 соответствует t1.id, но не какое-либо другое поле, сделайте

SELECT t1.id, t2.id FROM table2 t2
INNER JOIN table1 t1 ON (t2.t1_id = t1.id AND not(t2.fieldx <=> t1.fieldx))

Обратите внимание, что это также исключит строки, в которых оба значения fieldx равны null.
Если выне хочу, чтобы это заменило <=> на =.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...