Присоединяйтесь к более чем двум таблицам по одним и тем же столбцам с помощью предложения Oracle USING

У меня есть 3 таблицы: Таблица1, Таблица2 и Таблица3. Три таблицы содержат 3 одинаковых столбца SAMECOL1, SAMECOL2 и SAMECOL3. Обе таблицы Table1 и Table2 имеют столбец MY_PK_COL, который является первичным ключом Table1.

Когда я использую этот запрос в SQL Developer, я получаю сообщение об ошибке:

SELECT * FROM Table1
INNER JOIN Table2 ON Table1.MY_PK_COL = Table2.MY_PK_COL 
JOIN Table3 USING (SAMECOL1, SAMECOL2, SAMECOL3)
  1. 00000 - "столбец определен неоднозначно"

Но когда я использую это, все в порядке:

SELECT * FROM Table1
JOIN Table2 USING (MY_PK_COL, SAMECOL1, SAMECOL2, SAMECOL3)
JOIN Table3 USING (SAMECOL1, SAMECOL2, SAMECOL3)

Если я правильно понимаю, в первом запросе 3 столбца SAMECOLx переименовываются с такими псевдонимами, как SAMECOL1_1, SAMECOL2_1, SAMECOL3_1, поэтому это не должно быть проблемой для второго соединения с предложением USING (неоднозначная вещь).

Итак, в чем проблема с первым запросом?

🤔 А знаете ли вы, что...
SQL поддерживает создание представлений (VIEW), что позволяет абстрагироваться от структуры таблицы при выполнении запросов.


1
52
2

Ответы:

Решено

Если я правильно понимаю, в первом запросе 3 столбца SAMECOLx переименовываются с такими псевдонимами, как SAMECOL1_1, SAMECOL2_1, SAMECOL3_1

Нет. Операция соединения не переименовывает столбцы. Если вы запросили только эти две таблицы с этим соединением, то ваш клиент выбирает добавление части _1 при отображении результатов; это не часть набора результатов.

То, что вы видите, зависит от вашего клиента и от того, как вы его запускаете. Например, SQL Developer изменит заголовки столбцов, как вы описываете в окне «Результат запроса», если вы запустите его как запрос (оператор запуска или управление-ввод); но если вы запустите его как скрипт (запустите скрипт или F5), то он не сделает этого в окне «Вывод скрипта». Как и SQL*Plus или SQLcl.

Итак, первая часть

Table1
INNER JOIN Table2 ON Table1.MY_PK_COL = Table2.MY_PK_COL 

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

JOIN Table3 USING (SAMECOL1, SAMECOL2, SAMECOL3)

не знает, какой из двух столбцов вы имеете в виду - он не может различить Table1.SAMECOL1 и Table2.SAMECOL2. Вы знаете, что это одни и те же данные, но в запросе нет ничего, что говорило бы об этом.

Во второй форме первый USING устраняет эту двусмысленность:

Table1
JOIN Table2 USING (MY_PK_COL, SAMECOL1, SAMECOL2, SAMECOL3)

имеет только одну проекцию SAMECOL1, которая как бы не из обеих исходных таблиц, а ни из одной из них.

Вы можете увидеть разницу в этой скрипте, которая не использует псевдонимы для повторяющихся столбцов в первом запросе, как вы предполагали (и как это делает ваш клиент):

SELECT * FROM Table1
INNER JOIN Table2 ON Table1.MY_PK_COL = Table2.MY_PK_COL
MY_PK_COL САМЕКОЛ1 САМЕКОЛ2 САМЕКОЛ3 MY_PK_COL САМЕКОЛ1 САМЕКОЛ2 САМЕКОЛ3 42 1 2 3 42 1 2 3
SELECT * FROM Table1
JOIN Table2 USING (MY_PK_COL, SAMECOL1, SAMECOL2, SAMECOL3)
MY_PK_COL САМЕКОЛ1 САМЕКОЛ2 САМЕКОЛ3 42 1 2 3

Если вы используете только первое соединение, вы увидите очевидную разницу

SELECT * FROM Table1
JOIN Table2 USING (MY_PK_COL, SAMECOL1, SAMECOL2, SAMECOL3);

 MY_PK_COL   SAMECOL1   SAMECOL2   SAMECOL3
---------- ---------- ---------- ----------
         1          1          1          1
         
SELECT * FROM Table1
INNER JOIN Table2 ON Table1.MY_PK_COL = Table2.MY_PK_COL;

 MY_PK_COL   SAMECOL1   SAMECOL2   SAMECOL3  MY_PK_COL   SAMECOL1   SAMECOL2   SAMECOL3
---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
         1          1          1          1          1          1          1          1

Итак, дело в том, что при использовании ON conditionselect * возвращает все столбцы из обеих таблиц, что приводит к вашей проблеме.

Соединение с USING column возвращает используемые столбцы только один раз - к сожалению, я не могу найти документацию по этому поведению, самое близкое описание

Во внешнем объединении с предложением USING запрос возвращает один столбец, объединяющий два соответствующих столбца в объединении.