Рассматривается описание оператора SELECT (DML). Примеры приведены в среде Oracle Database 18c Express Edition.
В посте рассматривается базовое описание оператора SELECT, относящийся к группе операторов DML (Data Manipulation Language).
Согласно документации Oracle, к DML относятся следующие операторы: CALL, DELETE, EXPLAIN PLAN, INSERT, LOCK TABLE, MERGE, SELECT, UPDATE. SELECT используется для извлечения данных из одной или более таблиц, объектных таблиц, представлений, объектных представлений или материализованных представлений. Далее рассматривается извлечения данных из одной таблицы. Все SQL-запросы будут выполнены в Oracle Database 18c Express Edition, в частности к таблице employees пользователя hr. При необходимости можно прочитать: о способе разблокировки и доступа к пользователю hr в Oracle Database 18c Express Edition.
Для извлечения данных из таблицы следует указать ее название и список интересующих столбцов или символ звездочка (ниже будет описание символа звездочки).
Пример 1. С помощью оператора SELECT выполняется извлечение данных из столбцов first_name, last_name, phone_number, salary таблицы employees. После оператора SELECT надо указать имена столбцов, из которых нужно получить данные. После FROM указывается имя таблицы. При запуске SQL-запроса в SQL*Plus необходимо ставить символ точки с запятой (;) в конце запроса. Далее все примеры будут выполнены в Oracle SQL Developer. В Oracle SQL Developer допускается не использовать точку с запятой (;).
SELECT first_name, last_name, phone_number, salary FROM employees
Если необходимо получить данные из всех существующих столбцов таблицы, то вместо того, чтобы перечислять имена всех этих столбцов, можно использовать символ звездочки (*). Символ звездочки представляет собой альтернативное решение для перечисления всех столбцов в разделе SELECT SQL-запроса.
Пример 2. В SQL-запросе используется символ звездочки, чтобы получить значения всех столбцов таблицы employees:
SELECT * FROM employees
Если в разделе SELECT SQL-запроса перечислить наименования столбцов в нижнем регистре, то на выходе можно увидеть название столбцов в верхнем регистре.
Это связано с тем, что название таблиц и ее колонок автоматически создаются в верхнем регистре при выполнении команд CREATE TABLE или ALTER TABLE. Например, при извлечении данных из столбца salary таблицы employees видно, что название столбца автоматически конвертировался в SALARY. Не всегда возникает необходимость использовать заголовки, сгенерированные после выполнения SELECT. При необходимости можно самому задавать устраивающие заголовки столбцов используя псевдонимы (aliases). В следующем примере для значения столбца email присваивается псевдоним Эл. почта.SELECT last_name, email "Эл. почта" FROM employees
Кроме того, можно использовать псевдонимы в сочетании с ключевым словом AS:
SELECT last_name, email AS "Эл. почта" FROM employees
Есть возможность объединить результаты двух или более столбцов и потом вывести их в одном столбце под общим заголовком для удобного чтения. Для этого используется символ конкатенации (||) или функция CONCAT. Например, в столбцах first_name и last_name таблицы employees содержится имя и фамилия сотрудника. В предыдущих примерах значения из этих столбцов выбирались и отображались по отдельности. Ниже при помощи символа конкатенации выполняется объединение значений этих двух столбцов для удобства чтения.
SELECT first_name || last_name AS "Имя и фамилия" FROM employees
Результат sql-запроса показывает, что значения двух столбцов отображаются в одном столбце. Для обеспечения пробела между значениями этих двух столбцов запрос доработан с помощью двух символов апостроф и пробела между ними.
SELECT first_name || ' ' || last_name AS “Имя и фамилия” FROM employees
Для ограничения числа строк по какому-то признаку во время выполнения оператора SELECT, можно использовать фразу WHERE. Это фраза является часто используемой, так как в таблицах обычно хранятся огромное количество строк, а на практике часто необходимо только очень небольшое подмножество этих строк. Фраза WHERE используется после FROM.
В следующем примере фраза WHERE используется для выборки из таблицы employees строки, в которой в столбце last_name содержится имя ‘Steven’:
SELECT * FROM employees WHERE employee_name = 'Steven'
Запрос вернул 2 строки.
В предыдущем примере во фразе WHERE было использовано условие сравнения – равенство (=). Помимо условия сравнения равенство есть и другие условия сравнения (условие), которые можно использовать во фразе WHERE. В приведенной ниже таблице перечисляются возможные условия сравнения:
Условие сравнения | Описание |
= | Равно |
<> или != | Не равно |
< | Меньше чем |
> | Больше чем |
<= | Меньше или равно |
>= | Больше или равно |
ANY | Любой из |
ALL | Все |
В следующем примере во фразе WHERE используется условие неравенства (<>) для отбора строк таблицы employees, в которых salary не равен 17000.
SELECT * FROM employees WHERE salary <> 17000
В следующем примере из таблицы employees будут извлечены значения столбцов first_name, last_name и salary из строк , в которых salary больше 5000:
SELECT first_name, last_name, salary FROM employees WHERE salary > 5000
Условие ANY можно использовать во фразе WHERE для сравнения значения с каким-либо из значений в списке. Перед условием ANY необходимо указать одно из условий сравнения: =, <>, <= или =>.
В приведенном ниже примере с помощью SELECT извлекаются те данные из таблицы employees, которые в столбце salary имеют значение больше одного из этих значений: 10000, 12000 или 170000:
SELECT * FROM employees WHERE salary > ANY (10000,120000,17000)
SQL-запрос вернул 15 (пятнадцать) строк из 107. Данный результат показывает, что у 15 сотрудников зарплата больше 10000 или 12000 или 17000.
Условие ALL используется во фразе WHERE для сравнения значения со всеми значениями в списке. Перед условием ALL необходимо использовать одно из условий сравнения: =,<> , <, >, <= или >=. В приведенном ниже примере условие ALL используется для получения из таблицы employees строк, в которых столбец salary больше всех значений: 10000, 12000 или 150000:
SELECT * FROM employees WHERE employee_id > ALL (10000,120000,15000)
В данном примере sql-запрос вернул 3 (три) строки. Результат говорит о том, что только у трех сотрудников зарплата больше 10000 и 12000 и 17000.
Кроме рассмотренных условий сравнения для фразы WHERE есть нижеперечисленные условия (см. таблицу ниже), которые позволяют ограничить число строк по нужному признаку во время выполнения оператора SELECT:
- LIKE – Находит совпадающие шаблоны в строках
- IN – Проверяет по спискам значений
- BETWEEN – Проверяет по диапазону значений
- IS NULL – Проверяет на пустые значения
Кроме того, можно использовать условие NOT для отрицания значений условий LIKE, IN, BETWEEN и IS NULL:
- NOT LIKE
- NOT IN
- NOT BETWEEN
- IN NOT NULL
Ниже предоставлено описание условий LIKE, IN, NOT, BETWEEN, NOT NULL.
Условие LIKE во фразе WHERE можно использовать для поиска и проверки значений по определенному шаблону. При использовании шаблона можно использовать комбинацию обычных символов и следующих двух групповых символов:
- Символ подчеркивания (_) Соответствует одному символу в определенной позиции
- Символ процента (%) Соответствует любому количеству символов, начинающихся в специфицированной позиции
В следующем примере используется условие LIKE с шаблоном вида ‘_t%’, для извлечения данных из столбца first_name таблицы employees. Символ подчеркивания (_) перед буквой t означает любой символ в первой позиции значения столбца, а символ процента (%) – любые символы, следующие после t:
SELECT * FROM employees WHERE first_name LIKE '_t%'
Результат sql-запроса показывает, что у трех сотрудников в имени (колонка first_name) второй буквой является t.
В следующем примере условие NOT LIKE используется для получения строк, которые отличаются от выбранных предыдущим запросом – противоположное, то есть все строки в столбце first_name содержащие значения, где во второй позиции нет буквы t:
SELECT * FROM employees WHERE first_name NOT LIKE '_t%'
Как и ожидалось, были отобраны все 104 строки кроме тех 3 строк, которые были отобраны предыдущим запросом.
Во фразе WHERE можно использовать условие IN для извлечения только тех строк из таблицы, которые содержат значения указанного столбца фразы WHERE из предлагаемого списка. В следующем примере используется условие IN для отбора тех строк таблицы employees, в которых значение столбца employee_id равно 200, 201 или 205:
SELECT * FROM employees WHERE employee_id IN (200,201,205)
Запрос вернул 3 строки, в которых у сотрудников значение для колонки employee_id содержит 200 или 201 или 205.
Если IN заменить условием NOT IN, то будут отобраны все 104 строки, кроме указанных 3 строк, которые получены в примере выше.
Условие BETWEEN во фразе WHERE используется в тех случаях, когда необходимо отобрать строки, значения столбцов которых попадают в определенный интервал. В следующем примере условие BETWEEN используется для отбора из таблицы employees строк, где значение столбца salary попадает в диапазон от 10000 до 12000 (включительно):
SELECT * FROM employees WHERE salary BETWEEN (10000 AND 12000)
Результат показывает, что у 11 (одиннадцать) сотрудников значение для колонки зарплата (salary) находится в интервале от 10000 до 12000 (включительно).
Во фразе WHERE также могут быть использованы логические условия, которые позволяют ограничивать число отбираемых строк на основании логических условий. Допустимые логические условия перечислены в приведенной ниже таблице:
- x AND y – Возвращает значение true (истина), если х и y имеют значение true
- x or y – Возвращает значение true (истина), если либо х, либо у имеют значение true
- NOT x – Возвращает true, если х имеет значение false; воз¬вращает false, если х имеет значение true
Следующий пример показывает применение условия AND для извлечения строк из таблицы employees, для которых удовлетворяются оба поставленных условия:
- Значение для столбца salary больше 10000.
- Значение для столбца employee_id больше 100.
SELECT * FROM employees WHERE salary > 10000 AND employee_id > 100
На основе результата запроса можно сказать, что поставленным двум условия удовлетворяют значения только из 14 (четырнадцать) строк.
В следующем примере условие OR используется для отбора строк из таблицы employees, для которых выполняется одно из следующих условий:
• Значение для столбца salary больше 10000
• Значение для столбца employee_id больше 100
SELECT * FROM employees WHERE salary > 10000 OR employee_id > 100
После выполнения данного запроса получили множество строк (больше чем при использовании условия AND) из общего массива строк – 107, так как условие OR возвращает всех сотрудников, у кого зарплата больше 10000 (независимо от значения employee_id) или у кого значение employee_id больше 100 (независимо от значения в колонке salary).
При необходимости во фразе WHERE можно совместно использовать несколько логических условий для создания сложного логического выражения.
На этом завершается базовое описание оператора SELECT, относящийся к группе операторов DML (Data Manipulation Language)
Подзапросы SQL
Подзапрос представляет собой оператор SELECT
, вложенный в тело другого оператора.
Кодирование подзапроса подчиняется тем же правилам, что и кодирование простого оператора SELECT
. Внешний оператор использует результат выполнения внутреннего оператора для определения окончательного результата.
По количеству возвращаемых значений подзапросы разделяются на два типа:
- скалярные подзапросы, которые возвращают единственное значение;
- табличные подзапросы, которые возвращают множество значений.
По способу выполнения выделяют два типа подзапросов:
- простые подзапросы;
- сложные подзапросы.
Подзапрос называется простым, если он может рассматриваться независимо от внешнего запроса. СУБД выполняет такой подзапрос один раз и затем помещает его результат во внешний запрос.
Сложный подзапрос не может рассматриваться независимо от внешнего запроса. В этом случае выполнение оператора начинается с внешнего запроса, который отбирает каждую отдельную строку таблицы. Для каждой выбранной строки СУБД выполняет подзапрос один раз.
Спонсор поста
Простые скалярные подзапросы
Приведем примеры простых скалярных подзапросов.
База данных, используемая в примерах, находится в этом посте.
Пример 1.
Определить наименования деталей, цена которых больше цены детали ‘болт’.
SELECT dname FROM D WHERE dprice > (SELECT dprice FROM D WHERE dname = ’болт’)
Данный подзапрос относится к скалярным, так как возвращает единственное значение — цену детали ‘болт’.
Подзапрос является простым, потому что он может рассматриваться независимо от внешнего запроса. СУБД сначала выполняет подзапрос, в результате чего получает цену детали ‘болт’ — значение 10, а затем помещает это значение во внешний запрос и выполняет его.
Пример 2.
Определить номера деталей, цена которых меньше средней цены деталей.
SELECT dname FROM D WHERE dprice < (SELECT AVG(dprice) FROM D)
Пример 3.
Определить номер поставщика, выполнившего поставку с минимальным объемом.
SELECT pnum FROM PD WHERE volume = (SELECT min(volume) FROM PD)
Пример 4.
Определить номера деталей, которых поставляется больше, чем деталей с номером 2.
SELECT pnum FROM PD GROUP BY dnum HAVING sum(volume) > (SELECT sum(volume) FROM PD WHERE dnum = 2)
Подзапросы можно использовать не только в предложении WHERE
, но и в других предложениях оператора SELECT
, например, в самом предложении SELECT
.
Пример 5.
Вывести следующую информацию о деталях: наименование, цена, отклонение от средней цены.
SELECT dname, dprice, dprice - (SELECT AVG(dprice) FROM PD) AS dif FROM PD
В результате получим таблицу:
dname | dprice | dif |
---|---|---|
болт | 10 | -10 |
гайка | 20 | 0 |
винт | 30 | 10 |
Простые табличные подзапросы
Если подзапрос возвращает множество значений, то его результат следует обрабатывать специальным образом. Для этого предназначены операции IN
, ANY
, SOME
и ALL
.
Такие операции могут использоваться с подзапросами, возвращающими таблицу, состоящую из одного столбца значений.
Операция
IN
Операция IN
осуществляет проверку на принадлежность значения множеству, которое получается после выполнения подзапроса.
Пример 6.
Определить наименования поставщиков, которые поставляют детали.
SELECT pname FROM P WHERE pnum in (SELECT pnum FROM PD)
Такой подзапрос относится к табличным, так как возвращает множество значений. Подзапрос является простым, потому что он может рассматриваться независимо от внешнего запроса.
СУБД сначала выполняет подзапрос, в результате чего получает множество номеров поставщиков, которые поставляют детали. Затем СУБД проверяет номер каждого поставщика из таблицы P на принадлежность полученному множеству. При вхождении в множество наименование поставщика помещается в результирующую таблицу.
Пример 7.
Определить наименования поставщиков, которые не поставляют деталь с номером 2.
SELECT pname FROM P WHERE pnum not in (SELECT pnum FROM PD WHERE dnum = 2)
Пример 8.
Определить наименования поставщиков, которые поставляют только деталь с номером 1.
SELECT pname FROM PD WHERE pnum in (SELECT pnum FROM PD WHERE dnum = 1) AND pnum not in (SELECT pnum FROM PD WHERE dnum <> 1)
Операции
ANY
, SOME
, ALL
Если подзапросу предшествует ключевое слово ANY
, то условие сравнения считается выполненным, когда оно выполняется хотя бы для одного из значений, которые получаются после выполнения подзапроса.
Если подзапросу предшествует ключевое слово ALL
, то условие сравнения считается выполненным, только если оно выполняется для всех значений, которые получаются после выполнения подзапроса.
Если в результате выполнения подзапроса получено пустое множество, то для операции ALL
условие сравнения будет считаться выполненным, а для ключевого слова ANY
— невыполненным.
Ключевое слово SOME
является синонимом ANY
и используется для повышения наглядности текстов запросов.
Пример 9.
Определить наименования поставщиков, которые поставляют детали.
SELECT pname FROM P WHERE pnum = ANY(SELECT pnum FROM PD)
Такой подзапрос относится к табличным, так как возвращает множество значений. Подзапрос является простым, потому что он может рассматриваться независимо от внешнего запроса.
СУБД сначала выполняет подзапрос, в результате чего получает множество номеров поставщиков, которые поставляют детали. Затем СУБД проверяет номер каждого поставщика из таблицы P на равенство хотя бы одному из номеров из полученного множества. При выполнении условия наименование поставщика помещается в результирующую таблицу.
Пример 10.
Определить наименование детали с максимальной ценой.
SELECT dname FROM D WHERE dprice >= ALL(SELECT dprice FROM PD)
Последний пример можно решить следующим способом:
SELECT dname FROM D WHERE dprice = (SELECT max(dprice) FROM PD)
Сложные табличные подзапросы
Операция EXISTS
Результат выполнения таких операций представляет собой значения TRUE
или FALSE
.
Для операции EXISTS
результат равен TRUE
, если в возвращаемой подзапросом таблице присутствует хотя бы одна строка.
Если в результирующей таблице подзапроса пуста, то операция EXISTS
возвращает значение FALSE
. Для операции NOT EXISTS
используются обратные правила обработки.
Поскольку обе операции проверяют лишь наличие строк в результирующей таблице подзапроса, то эта таблица может содержать произвольное количество столбцов.
Пример 11.
Определить наименования поставщиков, которые поставляют детали.
SELECT pname FROM P WHERE EXISTS(SELECT * FROM PD WHERE PD.pnum = P.pnum)
Такой подзапрос относится к табличным, так как возвращает множество значений. Подзапрос является сложным, потому что он не может выполняться независимо от внешнего запроса.
В этом случае выполнение оператора начинается с внешнего запроса, который поочередно отбирает каждую отдельную строку таблицы P. Для каждой выбранной строки СУБД выполняет подзапрос один раз. В результирующую таблицу помещаются только те наименования поставщиков, для которых подзапрос возвращает хотя бы одну строку.
Первой выбирается строка с информацией о поставщике Иванов. В подзапрос вместо P.pnum подставляется значение 1 (номер поставщика Иванова), после чего подзапрос выполняется.
Подзапрос возвращает три первых строки из таблицы PD, соответствующие поставкам Иванова, поэтому результат операции EXISTS
равен TRUE
, и наименование Иванов помещается в результирующую таблицу.
Аналогично результат получается для поставщиков Петров и Сидоров. При выборе строки с информацией о поставщике Кузнецов, подзапрос возвращает пустое множество, поэтому результат операции EXISTS
равен FALSE
, и наименование Кузнецов не помещается в результирующую таблицу.
Создание самосоединений
Самосоединение это обычное соединение языка SQL, которое соединяет таблицу саму с собой. Такое соединение позволяет сравнивать значения, хранящиеся в одном столбце таблицы.
При самосоединении используются псевдонимы таблиц, которые позволяют различать соединяемые копии таблиц. Псевдонимы вводятся в предложении FROM
и используются как обычные имена таблиц.
Пример 12.
Определить наименования поставщиков, которые поставляют и деталь с номером 1, и деталь с номером 2.
Один из вариантов решения задачи можно записать с помощью подзапроса следующим образом.
SELECT pnum FROM PD WHERE dnum = 1 AND pnum in (SELECT pnum FROM PD WHERE dnum = 2)
Тот же самый результат можно получить используя соединение таблицы PD с ее копией, назовем ее PD1, следующим образом:
SELECT PD. pnum FROM PD INNER JOIN PD AS PD1 ON PD.pnum = PD1.pnum WHERE PD.dnum = 1 AND PD1.dnum = 2
Пример 13.
Определить наименования поставщиков, которые поставляют и деталь с номером 1, и деталь с номером 2, и деталь с номером 3.
SELECT PD.pnum FROM (PD INNER JOIN PD AS PD1 ON PD.pnum=PD1.pnum) INNER JOIN PD AS PD2 ON PD1.pnum=PD2.pnum WHERE PD.dnum=1 AND PD1.dnum=2 AND PD2.dnum=3
Резюмирую
Из этой статьи вы узнали что такое подзапрос в SQL. Теперь вы легко отличите скалярный запрос от табличного, и простой запрос от сложного.
Также мы рассмотрели на примерах такие операции, как IN
, ANY
, SOME
и ALL
.
Вложенный оператор выбора в SQL Server
Почему не работает следующее?
ВЫБЕРИТЕ имя ИЗ (ВЫБЕРИТЕ имя ИЗ информации об агенте)
Думаю, я неправильно понимаю SQL, потому что я думал, что это вернет то же самое, что и
SELECT name FROM agentinformation
Разве внутренний оператор select не создает результирующий набор, который затем запрашивает внешний оператор SELECT?
- sql
- sql-сервер
- вложенный
- подзапрос
- запрос
Вам необходимо создать псевдоним для подзапроса.
ВЫБЕРИТЕ имя ИЗ (ВЫБЕРИТЕ имя ИЗ информации об агенте) a
или, чтобы быть более точным,
SELECT a.name FROM (SELECT name FROM agentinformation) a
4
Ответ Джо Стефанелли уже верен.
ВЫБЕРИТЕ имя ИЗ (ВЫБЕРИТЕ имя ИЗ информации об агенте) как
Нам необходимо создать псевдоним подзапроса, потому что для запроса требуется табличный объект, который мы получим, создав псевдоним для подзапроса. Концептуально результаты подзапроса подставляются во внешний запрос. Поскольку нам нужен объект таблицы во внешнем запросе, нам нужно создать псевдоним внутреннего запроса.
Операторы, включающие подзапрос, обычно принимают одну из следующих форм:
- WHERE выражение [NOT] IN (подзапрос)
- ГДЕ выражение оператор сравнения_[ЛЮБОЙ | ВСЕ] (подзапрос)
- ГДЕ [НЕ]СУЩЕСТВУЕТ (подзапрос)
Проверьте дополнительные правила и типы подзапросов.
Дополнительные примеры вложенных подзапросов.
IN / NOT IN — этот оператор берет выходные данные внутреннего запроса после выполнения внутреннего запроса, которые могут содержать ноль или более значений, и отправляет их во внешний запрос. Затем внешний запрос извлекает все совпадающие строки [оператор IN] или не совпадающие строки [оператор NOT IN].
ЛЮБОЙ — [> ЛЮБОЙ или ЛЮБОЙ оператор берет список значений, созданных внутренним запросом, и извлекает все значения, которые больше минимального значения списка.
напр. >ANY(100,200,300), оператор ANY извлечет все значения больше 100.
- ALL – оператор [>ALL или ALL берет список значений, созданных внутренним запросом, и извлекает все значения, которые больше максимального списка.
напр. >ALL(100,200,300), оператор ALL выберет все значения больше 300.
- EXISTS – Ключевое слово EXISTS создает логическое значение [ИСТИНА/ЛОЖЬ]. EXISTS проверяет наличие строк, возвращаемых подзапросом.
0
ПОПРОБУЙТЕ ЭТО
'выберите *,(ВЫБЕРИТЕ количество (id) ИЗ продуктов, ГДЕ user_id = users.id) как products_count от пользователей ORDER BY products_count DESC, ID DESC LIMIT 200
Зарегистрируйтесь или войдите в систему
Зарегистрируйтесь с помощью Google
Зарегистрироваться через Facebook
Зарегистрируйтесь, используя адрес электронной почты и пароль
Опубликовать как гость
Электронная почта
Требуется, но никогда не отображается
Опубликовать как гость
Электронная почта
Требуется, но не отображается
подзапросов в инструкциях SELECT
подзапросов в инструкциях SELECT
|
Следующие ситуации определяют типы подзапросов, которые поддерживает сервер баз данных:
- Оператор SELECT , вложенный в список SELECT другого оператора SELECT
- оператор SELECT , вложенный в предложение WHERE другого оператора SELECT (или в оператор INSERT , DELETE или UPDATE )
Каждый подзапрос должен содержать предложение SELECT и предложение FROM . Подзапросы могут быть коррелированными или некоррелированными . Подзапрос (или внутренний SELECT оператор) коррелируется, когда получаемое им значение зависит от значения, созданного внешним SELECT оператором, который его содержит. Любой другой вид подзапроса считается некоррелированным.
Важной особенностью коррелированного подзапроса является то, что, поскольку он зависит от значения из внешнего SELECT , он должен выполняться повторно, по одному разу для каждого значения, которое производит внешний SELECT . Некоррелированный подзапрос выполняется только один раз.
Вы можете создать оператор SELECT с подзапросом для замены двух отдельных операторов SELECT .
Подзапросы в операторах SELECT позволяют выполнять следующие действия:
- Сравнение выражения с результатом другого оператора SELECT
- Определить, включают ли результаты другого оператора SELECT выражение
- Определить, выбирает ли другая инструкция SELECT какие-либо строки
Необязательное предложение WHERE в подзапросе часто используется для сужения условия поиска.
Подзапрос выбирает и возвращает значения первому или внешнему оператору SELECT . Подзапрос может не возвращать значения, одно значение или набор значений, как показано ниже:
- Если подзапрос возвращает без значения , запрос не возвращает никаких строк. Такой подзапрос эквивалентен нулевому значению.
- Если подзапрос возвращает одно значение , это значение имеет форму либо одного агрегатного выражения, либо ровно одной строки и одного столбца. Такой подзапрос эквивалентен одному числу или символьному значению.
- Если подзапрос возвращает список или набор значений, значения представляют либо одну строку, либо один столбец.
Подзапросы в списке выбора
Подзапрос может появиться в списке выбора другого оператора SELECT . Запрос 5-20 показывает, как вы можете использовать подзапрос в списке выбора, чтобы получить общую стоимость доставки (из таблицы заказов ) для каждого клиента в таблице клиентов . Вы также можете написать этот запрос как соединение между двумя таблицами.
Запрос 5-20
- ВЫБРАТЬ customer.customer_num,
- (ВЫБЕРИТЕ СУММУ(ship_charge)
- ОТ заказов
- ГДЕ клиент.номер_клиента = заказы.номер_клиента)
- КАК total_ship_chg
- ОТ заказчика
Результат запроса 5-20 |
Подзапросы в пунктах WHERE
В этом разделе описываются подзапросы, которые встречаются в виде инструкции SELECT 9.0157 вложил в предложение WHERE другого оператора SELECT .
Следующие ключевые слова вводят подзапрос в предложение WHERE оператора SELECT :
- ВСЕ
- ЛЮБОЙ
- В
- СУЩЕСТВУЕТ
Вы можете использовать любой оператор отношения с ВСЕ и ЛЮБОЙ , чтобы сравнить что-то с каждым из ( ALL ) или любому из ( ANY ) значений, выдаваемых подзапросом. Вы можете использовать ключевое слово SOME вместо ANY . Оператор IN эквивалентен = ANY . Чтобы создать противоположное условие поиска, используйте ключевое слово NOT или другой оператор отношения.
Оператор EXISTS проверяет подзапрос на наличие каких-либо значений; то есть он спрашивает, не является ли результат подзапроса нулевым. Вы не можете использовать EXISTS ключевое слово в подзапросе, который содержит столбец с типом данных TEXT или BYTE .
Синтаксис, который вы используете для создания условия с подзапросом, см. в Informix Guide to SQL : Syntax .
Использование ВСЕХ
Используйте ключевое слово ALL перед подзапросом, чтобы определить, верно ли сравнение для каждого возвращаемого значения. Если подзапрос не возвращает значений, условие поиска равно true 9.0158 . (Если он не возвращает никаких значений, условие истинно для всех нулевых значений. )
Запрос 5-21 перечисляет следующую информацию для всех заказов, содержащих товар, общая цена которого меньше общей цены для каждого товара в заказе с номером 1023.
Запрос 5-21
- ВЫБЕРИТЕ order_num, stock_num, manu_code, total_price
ИЗ товаров
WHERE total_price < ALL
(ВЫБЕРИТЕ total_price ИЗ товаров
WHERE order_num = 1023)
Результат запроса 5-21 |
Использование ЛЮБОГО
Используйте ключевое слово ANY (или его синоним SOME ) перед подзапросом, чтобы определить, верно ли сравнение хотя бы для одного из возвращаемых значений. Если подзапрос не возвращает значений, условием поиска является false . (Поскольку значений не существует, условие не может быть истинным ни для одного из них. )
Запрос 5-22 находит номер заказа для всех заказов, содержащих товар, общая цена которого больше, чем общая цена любой один из позиций в заказе № 1005.
Запрос 5-22
- ВЫБЕРИТЕ ОТЛИЧНЫЙ номер_заказа
ИЗ элементов
ГДЕ общая_цена > ЛЮБОЙ
(ВЫБЕРИТЕ общую цену
ИЗ элементов
ГДЕ номер_заказа = 1005)
Результат запроса 5-22 |
Однозначные подзапросы
Вам не нужно включать ключевое слово ВСЕ или ЛЮБОЙ , если вы знаете, что подзапрос может вернуть ровно одно значение в запрос внешнего уровня. Подзапрос, возвращающий ровно одно значение, можно рассматривать как функцию. Этот вид подзапроса часто использует агрегатную функцию, поскольку агрегатные функции всегда возвращают одиночные значения.
Запрос 5-23 использует агрегатную функцию MAX в подзапросе для поиска order_num для заказов, включающих максимальное количество волейбольных сеток.
Запрос 5-23
- ВЫБЕРИТЕ order_num ИЗ товаров
ГДЕ stock_num = 9
И количество =
(ВЫБЕРИТЕ МАКС (количество)
ИЗ товаров
ГДЕ stock_num = 9)
Результат запроса 5-23 |
Запрос 5-24 использует агрегатную функцию MIN в подзапросе для выбора товаров, общая цена которых превышает минимальную цену более чем в 10 раз.
Запрос 5-24
- ВЫБЕРИТЕ order_num, stock_num, manu_code, total_price
FROM товаров x
WHERE total_price >
(SELECT 10 * MIN (total_price)
FROM items
WHERE order_num = x.order_num)
Результат запроса 5-24 |
Коррелированные подзапросы
Запрос 5-25 — это пример коррелированного подзапроса, который возвращает список из 10 последних дат доставки в заказы табл. Он включает предложение ORDER BY после подзапроса для упорядочения результатов, поскольку вы не можете включить ORDER BY в подзапрос.
Запрос 5-25
- ВЫБЕРИТЕ po_num, ship_date ИЗ основных заказов
ГДЕ 10 >
(ВЫБЕРИТЕ СЧЕТЧИК (DISTINCT ship_date)
ИЗ заказов sub
ГДЕ sub.ship_date < main.ship_date)
AND ship_date НЕ НУЛЕВОЕ
ORDER BY ship_date, po_num
Подзапрос коррелирован, потому что число, которое он выдает, зависит от main.ship_date , значения, которое выдает внешний SELECT . Таким образом, подзапрос должен выполняться повторно для каждой строки, которую рассматривает внешний запрос.
Запрос 5-25 использует функцию COUNT для возврата значения в основной запрос. Затем предложение ORDER BY упорядочивает данные. Запрос находит и возвращает 16 строк с 10 последними датами доставки, как показано в результате запроса 5-25.
Результат запроса 5-25 |
Если вы используете коррелированный подзапрос, такой как запрос 5-25, в большой таблице, вы должны проиндексировать столбец ship_date для повышения производительности. В противном случае этот оператор SELECT неэффективен, поскольку он выполняет подзапрос один раз для каждой строки таблицы. Сведения об индексации и проблемах с производительностью см. в Руководстве администратора и в вашем Руководство по производительности .
Использование EXISTS
Ключевое слово EXISTS известно как квалификатор существования , потому что подзапрос истинен только в том случае, если внешний SELECT , как показывает запрос 5-26а, находит хотя бы одну строку.
Запрос 5-26a
- ВЫБЕРИТЕ УНИКАЛЬНОЕ имя_производителя, время выполнения
ИЗ производства
ГДЕ СУЩЕСТВУЕТ
(ВЫБЕРИТЕ * ИЗ ЗАПАСА
ГДЕ описание СООТВЕТСТВУЕТ '*обуви*'
И код_производства = код_запаса. ману)
Часто можно создать запрос с EXISTS , который эквивалентен запросу, использующему IN . В запросе 5-26b используется предикат IN для создания запроса, возвращающего тот же результат, что и в запросе 5-26a.
Запрос 5-26b
- ВЫБЕРИТЕ УНИКАЛЬНОЕ manu_name, lead_time
FROM stock, manufact
WHERE manu_code IN
(SELECT manu_code FROM stock
WHERE description MATCHES '*shoe*')
AND stock.manu_code = manufact.manu_code
Запрос 5-26a и запрос 5-26b возвращают строки для производителей, которые производят определенную обувь, а также время выполнения заказа на продукт. Результат запроса 5-26 показывает возвращаемые значения.
Результат запроса 5-26 |
Добавьте ключевое слово NOT к IN или к EXISTS , чтобы создать условие поиска, противоположное условию в предыдущих запросах. Вы также можете заменить != ВСЕ для НЕ В .
Запрос 5-27 показывает два способа сделать одно и то же. Один способ может позволить серверу базы данных выполнять меньше работы, чем другой, в зависимости от структуры базы данных и размера таблиц. Чтобы узнать, какой запрос может быть лучше, используйте команду SET EXPLAIN , чтобы получить список плана запроса. SET EXPLAIN обсуждается в Руководстве по производительности и Informix Guide to SQL : Syntax .
Запрос 5-27
- ВЫБЕРИТЕ номер_клиента, компанию ИЗ клиента
ГДЕ номер_клиента НЕ В
(ВЫБЕРИТЕ номер_клиента ИЗ заказов
ГДЕ номер_клиента = номер_заказа)
ВЫБЕРИТЕ номер_клиента, компанию ИЗ клиента
ГДЕ НЕ СУЩЕСТВУЕТ
(ВЫБЕРИТЕ * ИЗ заказов
ГДЕ клиент. номер_клиента = заказы.номер_клиента)
Каждый оператор в запросе 5-27 возвращает строки, показанные в результате запроса 5-27, которые идентифицируют клиентов, которые не размещали заказы.
Результат запроса 5-27 |
Ключевые слова EXISTS и IN используются для операции множества, известной как пересечение , а ключевые слова NOT EXISTS и NOT IN используются для операции множества, известной как разность . Эти концепции обсуждаются в разделе Операции над множествами.
Запрос 5-28 выполняет подзапрос к таблице элементов , чтобы идентифицировать все элементы в сток стол который еще не заказывали.
Запрос 5-28
- ВЫБЕРИТЕ * ИЗ запаса
ГДЕ НЕ СУЩЕСТВУЕТ
(ВЫБЕРИТЕ * ИЗ товаров
ГДЕ stock.stock_num = items.stock_num
AND stock.manu_code = items.manu_code)
Запрос 5-28 возвращает строки, показанные в Результате Запроса 5-28.
Результат запроса 5-28 |
Не существует логического ограничения на количество подзапросов a Оператор SELECT может иметь, но размер любого оператора физически ограничен, когда он рассматривается как строка символов. Однако этот предел, вероятно, больше, чем любое практическое утверждение, которое вы, вероятно, сочините.
Возможно, вы хотите проверить, правильно ли введена информация в базу данных. Один из способов найти ошибки в базе данных — написать запрос, возвращающий выходные данные только при наличии ошибок. Подзапрос этого типа служит своего рода контрольным запросом 9.0158 , как показывает запрос 5-29.
Запрос 5-29
- ВЫБЕРИТЕ * ИЗ товаров
ГДЕ общая_цена != количество *
(ВЫБЕРИТЕ цену за единицу ИЗ запаса
ГДЕ запас.инвентарный_номер = товарный_номер
И запасной.manu_code = items.manu_code)
Запрос 5-29 возвращает только те строки, для которых общая цена товара в заказе не равна цене единицы запаса, умноженной на количество заказа. Если скидка не применялась, вероятно, такие строки были неправильно введены в базу данных. Запрос возвращает строки только при возникновении ошибок. Если информация правильно вставлена в базу данных, строки не возвращаются.