sql - Запрос данных из двух таблиц


0

Есть две таблицы А и Б. Они имеют связь между собой. Необходимо получить данные из обеих таблиц в одном запросе. Делеаю такой запрос

SELECT a.id
FROM table_a a,
     table_b b
WHERE a.id = b.table_a
  AND (a.field_1 = false
  OR b.field_2 = true;

Проблема в следующем. Таблица А может содержать очень много запеисей, и только малый процент их присутствует в таблици B. Если я использую такую связь

WHERE a.id = b.table_a

То мне выберутся только те значения, которые присутствуют и в А, и в Б. Мне необходимо получить данные из соответствующие условию из таблицы А и данные по условию из таблицы Б. Если не использовать связывание, то данные будут дублироваться. Как построить запрос верным способом?

Таблица A

id SERIAL,
name text,
is_searchable boolean,

Таблица Б

id SERIAL
table_a reference,
is_dismissed boolean,

Я хочу получить все объекты из А, которые:

  1. Не сохранены как отклоненные в таблице Б (у которых is_dismissed == false)
  2. Те которые могут быть найдены (is_searchable == true)

В таблицу Б мы заносим объект в том случае, если мы хотим его сохранить (is_dismissed == true), или отбросить (is_dismissed == false).

Получается что запрос должен включать объекты из А "по условию" или объекты из А, которые имеют is_dismissed == true в таблице Б.

Проанализировав ответы понял, действительно надо использовать LEFT OUTER JOIN. Но загвоздка в том, что для разных таблиц разное условие. Те если я анализирую таблицу А то мне надо смотреть только лишь значение поля is_searchable, а если таблицу Б, то только значение is_dismissed. Следовательно, кроме UNION, вроде, нет альтернатив.

Источник
  •  2573
  •  5
  • 9 янв 2015 2015-01-09 07:25:57
Т.е. в Б есть строки, которые не указывают на A? (Вряд ли) Составьте таблицу searheable true false is_dismissed true ? ? false ? ? null ? ? и поставьте крестики, при каких комбинациях объект попадает в результат — 6 янв 20122012-01-06 12:34:53.000000

5 ответов

0
  1. UNION

Выборка из нескольких таблиц последовательно.

UNION действует как SELECT DISTINCT, т.е. отбрасывает повторяющиеся значения. чтобы этого избежать, нужно использовать оператор UNION ALL

(SELECT i, c FROM t1 ORDER BY i DESC)
UNION
(SELECT i, d FROM t2 ORDER BY i)
  • 6 янв 2015 2015-01-06 10:16:50
-4

По качеству вопроса: написано много букв, но так и не указано четко, какие значения имеют NULLы в этих логических столбцах.

По существу вменяемого мне вопроса могу показать следующее (синтаксические особенности мускула ВКЛЮЧЕНЫ):

SELECT *
FROM A
LEFT OUTER JOIN B ON B.table_a = A.id
WHERE A.is_searchable
AND (
B.id IS NULL
OR NOT B.is_dismissed
)

Всё это игриво намекает на COALESCE... А вопиет о неправильной схеме, где таблица-костыль B только мешает.

  • 6 янв 2012 2012-01-06 13:10:58
1

Задача действительно должна иметь решение как указано выше. Оператор JOIN - означает полное соединение, то есть взять все из левой таблицы и все из правой. Если использовать LEFT [OUTER] JOIN, то возьмется все из левой таблицы и то, что соответствует условию из правой. При операторе RIGHT [OUTER] JOIN тоже только наоборот. Синтаксис Леваятаблица LEFT(RIGHT) [OUTER] JOIN Праваятаблица Условие_соединения

  • 6 янв 2012 2012-01-06 10:53:04
2

Читайте, что значит LEFT OUTER JOIN (или RIGHT OUTER JOIN). Правда поля из таблицы, где отсутствует соответствующая запись будут иметь значение NULL. Возможно

SELECT a.id
FROM table_a a
LEFT OUTER JOIN table_b b ON a.id = b.table_a
AND (a.field_1 = false
     OR coalesce(b.field_2, true) = true);

(А у Вас true и false -- char или varchar?)

И что значит "данные из таблицы B", если написано select a.id?

95**Обновление.**95

Теперь непонятно с B.is_dismissed...

SELECT a.id,
       a.name
FROM table_a a
LEFT OUTER JOIN table_b b ON a.id = b.table_a
AND a.searchable
AND coalesce(b.is_dismissed, FALSE);

Т.е. те, у которых a.searchable и b.is_dismissed -- ложь, или соответствующая строка в B отсутствует. (Проверять -- не проверял)

  • 9 янв 2015 2015-01-09 07:12:46
Забыли сравнить is_dismissed с false. SELECT a.id, a.name FROM table_a a left outer join table_b b ON a.id = b.id AND a.searchable = true AND coalesce(b.is_dismissed, false) = false — 6 янв 20122012-01-06 12:02:49.000000
Обновил вопрос. — 6 янв 20122012-01-06 11:39:06.000000
Обновил ответ — 6 янв 20122012-01-06 11:14:07.000000
Так что же Вы хотите? (Желательно со описанием таблиц) — 6 янв 20122012-01-06 10:30:31.000000
Пробовал JOIN - результат один и тот же с a.id = b.tabel_a. Поля имеют булевый тип (значения t или f). — 6 янв 20122012-01-06 10:28:33.000000
1

Напишите по запросу для каждой таблицы и объедините их с помощью union.

  • 6 янв 2012 2012-01-06 10:15:15
union тут не поможет. нужно не объединять запросы, а исключить один из другого, т.е. операция не объединение множеств, а вычитание. — 6 янв 20122012-01-06 12:10:02.000000
Предложение UNION используется для объединения результатов нескольких запросов, повторения при этом исключаются. Документация SQL 6 янв 20122012-01-06 10:32:01.000000
На первый взгляд (в консоли) решение работает. Не могли бы вы подробно раскрыть тему, почему и какие последствия использования данного подхода присутствуют? — 6 янв 20122012-01-06 10:22:28.000000