Объединение нескольких таблиц с одним предложением объединения (sqlite) - PullRequest
0 голосов
/ 01 апреля 2020

Итак, я изучаю SQL (sqlite flavour) и просматриваю документацию sqlite JOIN-предложения , я считаю, что эти два утверждения действительны:

SELECT *
FROM table1
JOIN (table2, table3) USING (id);
SELECT *
FROM table1
JOIN table2 USING (id)
JOIN table3 USING (id)

(или даже, но это не относится к делу:

SELECT *
FROM table1
JOIN (table 2 JOIN table3 USING id) USING id

)

Теперь я видел второе (цепное соединение) много в SO вопросах по JOIN предложениям , но редко первый (сгруппированная таблица-запрос). Оба запроса выполняются в SQLiteStudio для неупрощенного случая.

Предоставляется минимальный пример здесь на основе этого кода

CREATE TABLE table1 (
    id     INTEGER PRIMARY KEY,
    field1 TEXT
)
WITHOUT ROWID;

CREATE TABLE table2 (
    id     INTEGER PRIMARY KEY,
    field2 TEXT
)
WITHOUT ROWID;

CREATE TABLE table3 (
    id     INTEGER PRIMARY KEY,
    field3 TEXT
)
WITHOUT ROWID;

INSERT INTO table1 (field1, id)
VALUES ('FOO0', 0),
       ('FOO1', 1),
       ('FOO2', 2),
       ('FOO3', 3);

INSERT INTO table2 (field2, id)
VALUES ('BAR0', 0),
       ('BAR2', 1),
       ('BAR3', 3);

INSERT INTO table3 (field3, id)
VALUES ('PIP0', 0),
       ('PIP1', 1),
       ('PIP2', 2);

SELECT *
FROM table1
JOIN (table2, table3) USING (id);

SELECT *
FROM table1
JOIN table2 USING (id)
JOIN table3 USING (id);

Может кто-нибудь объяснить, почему можно использовать один за другим, и если они не эквивалентны для определенных входных данных, приведите пример? Первый, безусловно, выглядит более чистым (по крайней мере, менее избыточным) для меня.


ВНУТРЕННЕЕ СОЕДИНЕНИЕ против ГДЕ предложение было предложено в качестве возможного дубликата. Хотя это касается использования , в качестве оператора соединения, я чувствую, что вопросы и особенно ответы в большей степени сосредоточены на удобочитаемости и использовании WHERE против JOIN. Мой вопрос больше об общей достоверности и возможных различиях в результатах (учитывая необходимые данные, чтобы вызвать разницу).

Ответы [ 2 ]

1 голос
/ 01 апреля 2020

SQLite не применяет правильный синтаксис соединения. Он видит оператор соединения ([INNER] JOIN, LEFT [OUTER] JOIN, et c., Даже запятую устаревшего синтаксиса соединения 1980-х), отдельный от условия (ON, USING). Это не хорошо, потому что это делает соединения более склонными к ошибкам. Документы SQLite, следовательно, являются очень плохой ссылкой для изучения объединений. (И сам SQLite - плохая система для их изучения, потому что СУБД не обнаруживает стандартные нарушения SQL присоединения.)

Придерживайтесь синтаксиса, определенного стандартом SQL (и никогда не используйте его объединенные запятыми объединения):

ОТ таблица [псевдоним]

((([[1015 * ВНУТРЕННИЙ ] | [( ВЛЕВО | FULL ) [ OUTER ]]) JOIN таблица [псевдоним] ( ON условия | USING ( столбцы ) )) | ( CROSS JOIN таблица [псевдоним]))

((([ INNER ] | [( LEFT | FULL ) [ OUTER ]]) JOIN таблица [псевдоним] ( ON условия | USING ( столбцы ) )) | ( CROSS JOIN таблица [псевдоним]))

...

(надеюсь, у меня есть получил это право :-) И я также надеюсь, что это достаточно читабельно: - | Я опустил NATURAL JOIN и RIGHT [OUTER] JOIN здесь, потому что я не рекомендую использовать их вообще.)

Для table вы можете разместить какое-нибудь имя таблицы или представление или подзапрос (последний включает круглые скобки, например (select * from mytable)). Столбцы в USING должны быть заключены в скобки (например, USING (a, b, c)). (Вы можете, конечно, использовать круглые скобки и в ON условиях, если вы найдете это более читабельным.)

В вашем случае правильно написанный запрос будет:

SELECT *
FROM table1
JOIN table2 USING (id)
JOIN table3 USING (id)

или Например,

SELECT *
FROM table1 t1
JOIN table2 t2 ON t2.id = t1.id
JOIN table3 t3 ON t3.id = t1.id

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

SELECT *
FROM table1 t1
JOIN table2 t2 ON t2.t1_id = t1.id
JOIN table3 t3 ON t3.t2_id = t2.id
0 голосов
/ 01 апреля 2020

После исправления синтаксиса они не одинаковы для всех таблиц, прочитайте синтаксис и определения операторов объединения в руководстве. Запятая является перекрестным соединением с более низким приоритетом, чем join объединение ключевых слов. SQL разных СУБД имеют вариации синтаксиса. Прочтите руководство. Некоторые допускают naked join для cross join.

using возвращает только один столбец для каждого указанного имени столбца & natural равно using для всех общих столбцов; но другие объединения основаны на перекрестном соединении и возвращают столбец для каждого входного столбца. Так как здесь таблицы 2 и 3 имеют столбцы идентификаторов, запятая возвращает таблицу с 2 столбцами идентификаторов. Тогда using (id) не имеет смысла, так как один операнд имеет 2 столбца идентификатора.

Если столбцы идентификаторов имеют только таблицы 1 и 3, очевидно, что второй запрос не может объединить 1 и 2 с использованием идентификатора.

Всегда есть много способов express вещей. В частности, СУБД SQL выполняют множество различных выражений одинаково. Исследуйте реализацию / оптимизацию реляционных запросов в целом, в SQL & в вашем руководстве СУБД. Как правило, простые варианты запросов, подобные этим, не влияют на выполнение самого простого механизма запросов. (Мы видим, что в SQLite cross join "оптимизатор запросов обрабатывает по-разному".)

Сначала научитесь писать простые запросы и узнайте, что делают операторы, каков их синтаксис и ограничения есть.

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