Разница между объединением с WHERE AND JOIN в предложении SELECT

У меня есть два запроса:

select id,(SELECT N.NAME
        FROM memuat.NETWORK N 
        join memuat.host H
        on N.ID = H.NETWORK ) as network_name
from memuat.host;
        
select id,(SELECT N.NAME
        FROM memuat.NETWORK N
        where N.ID = H.NETWORK ) as network_name
from memuat.host H;

Первый возвращает:

ORA-01427: single-row subquery returns more than one row
01427. 00000 -  "single-row subquery returns more than one row"

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

Второй запрос имеет коррелированный подзапрос. т.е. у него есть условие, ссылающееся на основную таблицу запросов H.

jarlh 14.02.2023 11:48

хорошо, но что делать? он возвращает одну строку?

moth 14.02.2023 11:49

Для каждой строки, выбранной из H, выполняется подзапрос. И оценивается условие N.ID = H.NETWORK в подзапросе.

jarlh 14.02.2023 11:50

но это будет работать только в том случае, если N.ID является уникальным индексом, верно?

moth 14.02.2023 12:00

Если в N есть две (или более) строки, удовлетворяющие условию, вы получите ошибку «ORA-01427: однострочный подзапрос возвращает более одной строки».

jarlh 14.02.2023 12:01

... И в этом случае столбец не должен называться идентификатором, поскольку идентификатор таблицы должен однозначно идентифицировать строку.

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

Ответы 1

Ответ принят как подходящий

В обоих запросах подзапрос выполняется один раз для каждой строки хоста.

Во втором запросе подзапрос:

select n.name from memuat.network n where n.id = h.network

Это получает сетевое имя для сетевого идентификатора хоста.

В вашем первом запросе подзапрос:

SELECT n.name
FROM memuat.network n 
JOIN memuat.host h ON n.id = h.network

Это получает список имен сетей. Вероятно, с большим количеством дубликатов, потому что мы получаем одну строку на хост.

Основной запрос в обоих случаях:

SELECT id, ( <subquery> ) AS network_name
FROM memuat.host h;

Здесь предполагается, что подзапрос возвращает одно значение, а именно сетевое имя хоста. Поскольку подзапрос во втором запросе возвращает одну строку с одним значением, это работает. Поскольку подзапрос в вашем первом запросе возвращает много строк, вы получаете сообщение об ошибке.

хорошо понял. так что речь идет не об использовании where или join, а о том, чтобы ссылаться на внешний запрос во внутреннем или нет? или в этом случае можно построить запрос, который ссылается на внешний запрос с оператором where? Я попытался сослаться на внешний запрос с помощью join, но мне это не удалось.

moth 14.02.2023 12:12

Во втором запросе внутренний запрос имеет ссылку на строку в основном запросе (h.network). Это называется коррелированным подзапросом. В первом запросе такой ссылки нет. Это автономный подзапрос, также называемый некоррелированным подзапросом. Отвечает ли это на ваш вопрос?

Thorsten Kettner 14.02.2023 12:18

Я хотел бы на самом деле знать, могу ли я изменить первый запрос, чтобы добиться того же, что и во втором запросе, но с сохранением ключевого слова join в выражении. это возможно сделать?

moth 14.02.2023 13:07

Да и смысла в этом просто не было бы. Подзапрос получает слишком много строк, потому что он выбирает сетевые имена для всех хостов вместо одного хоста в основном запросе. С помощью where host.id = h.id вы бы выбрали ту же самую строку хоста в подзапросе, которая уже есть в основном запросе (при условии, что эта таблица имеет уникальный идентификатор). Вы даже можете использовать для этого адрес строки: where host.rowid = h.rowid.

Thorsten Kettner 14.02.2023 14:33

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