Присоединяйтесь к более чем двум таблицам по одним и тем же столбцам с помощью предложения 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 (неоднозначная вещь).

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

ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
1
0
52
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 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

Спасибо очень понятный ответ! Но если у меня есть разные значения между столбцами SAMECOLx в таблице 1 и таблице 2, и я хочу выбрать один из них для сравнения с таблицей 3. Как я могу этого добиться?

mtnp 07.02.2023 19:13

Не используйте USING ни для одного соединения, а замените второе соединение ON правильно укажите условие — однако вы хотите выбрать, какое из них использовать.

Alex Poole 07.02.2023 19:15

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

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 запрос возвращает один столбец, объединяющий два соответствующих столбца в объединении.

Однако это зависит от вашего клиента; если вы запустите версию ON в SQL Developer как запрос (а не сценарий), то в окне результатов запроса он «услужливо» изменяет заголовки столбцов, поэтому вы видите SAMECOL1 и SAMECOL1_1, как описано в OP. Что делает его более запутанным и менее очевидным.

Alex Poole 07.02.2023 19:04

Я хотел сказать, что синтаксис USING возвращает используемые столбцы только один раз в запросе select *, а объединение с ON, наоборот, возвращает все столбцы из обеих таблиц. Я хотел указать на это ссылкой на документацию, которую, к сожалению, не могу найти @AlexPoole.

Marmite Bomber 07.02.2023 19:12

Да, я не согласен с этим, но ОП сбит с толку, потому что, когда они запускают этот запрос, они видят разные заголовки столбцов, поэтому он не выглядит двусмысленным — их клиент делает вид, что есть только один SAMECOL1, который они затем пытаются использовать, но это не так. В вашем выводе это очевидно, а в их нет...

Alex Poole 07.02.2023 19:18

Другие вопросы по теме