Подзапросы SQL

Содержание

Что такое подзапрос в SQL?

  • SQL подзапрос — это запрос, вложенный в другой запрос;
  • Подзапрос может использоваться:

o В инструкции SELECT;
o В инструкции FROM;
o В условии WHERE.

  • Подзапрос может быть вложен в инструкции SELECT, INSERT, UPDATE или DELETE, а также в другой подзапрос;
  • Подзапрос обычно добавляется в условие WHERE оператора SQL SELECT;
  • Можно использовать операторы сравнения, такие как >, <, или =. IN, ANY или ALL;
  • Подзапрос также называется внутренним запросом. Оператор, содержащий подзапрос, также называется внешним;
  • Внутренний запрос выполняется перед родительским запросом, чтобы результаты его работы могли быть переданы внешнему.

Подзапрос можно использовать в инструкциях SELECT, INSERT, DELETE или UPDATE для выполнения следующих задач:

  • Сравнения выражения с результатом запроса;
  • Определения того, включено ли выражение в результаты запроса;
  • Проверки того, выбирает ли запрос любые строки.

Синтаксис:

  • Подзапрос SQL (внутренний запрос) выполняется перед выполнением основного запроса (внешнего запроса);
  • Основной запрос использует результат выполнения подзапроса.

Примеры подзапросов SQL

В этом разделе мы рассмотрим, как использовать подзапросы. У нас есть следующие две таблицы: ‘student‘ и ‘marks‘ с общим полем ‘StudentID‘:

студенты

отметки

Теперь нужно составить запрос, определяющий всех студентов, которые получают лучшие отметки, чем студент со StudentID — «V002». Но мы не знаем отметок студента «V002».

Поэтому нужно составить два SQL подзапроса в Select. Один запрос возвращает отметки (хранятся в поле «Total_marks») для «V002», а второй запрос выбирает учеников, которые получают лучшие оценки, чем результат первого запроса.

Первый запрос:

SELECT *  
FROM `marks`  
WHERE studentid = 'V002';

Результат запроса:


Результатом запроса будет 80.

Используя результат этого запроса, мы написали еще один запрос, чтобы определить учеников, которые получают оценки лучше, чем 80.

Второй запрос:

SELECT a.studentid, a.name, b.total_marks
FROM student a, marks b
WHERE a.studentid = b.studentid
AND b.total_marks >80;

Результат запроса:


Два приведенных запроса определяют студентов, которые получают лучше оценки, чем студент StudentID «V002» (Abhay).

Можно объединить эти два запроса, вложив один запрос в другой. Подзапрос — это запрос внутри круглых скобок. Рассмотрим подзапроса в SQL пример:

Код SQL:

SELECT a.studentid, a.name, b.total_marks
FROM student a, marks b
WHERE a.studentid = b.studentid AND b.total_marks >
(SELECT total_marks
FROM marks
WHERE studentid =  'V002');

Результат запроса:


Графическое представление подзапроса SQL:

Подзапросы: общие правила

Ниже приведен синтаксис подзапроса:

Синтаксис:

(SELECT [DISTINCT] аргументы_подзапроса_для_отбора
FROM {имя_таблицы | имя_представления}
{ имя_таблицы | имя_представления } ...
[WHERE условия_поиска]
[GROUP BY выражение_объединения [,выражение_объединения] ...]
[HAVING условия_поиска])

Подзапросы: рекомендации по использованию

Ниже приведен ряд рекомендаций, которым нужно следовать при использовании SQL подзапросов:

  • Подзапрос должен быть заключен в круглые скобки;
  • Подзапрос должен указываться в правой части оператора сравнения;
  • Подзапросы не могут обрабатывать свои результаты, поэтому в подзапрос не может быть добавлено условие ORDER BY;
  • Используйте однострочные операторы с однострочными подзапросами;
  • Если подзапрос возвращает во внешний запрос значение null, внешний запрос не будет возвращать никакие строки при использовании операторов сравнения в условии WHERE.

Типы подзапросов

  • Однострочный подзапрос: возвращает ноль или одну строку;
  • Многострочный подзапрос: возвращает одну или несколько строк;
  • Многостолбцовый подзапрос: возвращает один или несколько столбцов;
  • Коррелированные подзапросы: указывают один или несколько столбцов во внешней инструкции SQL. Такой подзапрос называется коррелированным, поскольку он связан с внешней инструкцией SQL;
  • Вложенные подзапросы: подзапросы помещенные в другой подзапрос.

Также можно использовать подзапрос внутри инструкций INSERT, UPDATE и DELETE.

Подзапросы с инструкцией INSERT

Инструкция INSERT может использоваться с подзапросами SQL.

Синтаксис:

INSERT INTO имя_таблицы [ (столбец1 [, столбец2 ]) ]
SELECT [ *|столбец1 [, столбец2 ]
FROM таблица1 [, таблица2 ]
[ WHERE VALUE OPERATOR ];

Если мы хотим вставить заказы из таблицы ‘orders‘, для которых в таблице «neworder» значение advance_amount составляет 2000 или 5000, можно использовать следующий код SQL:

Пример таблицы: orders

ORD_NUM ORD_AMOUNT ADVANCE_AMOUNT ORD_DATE CUST_CODE AGENT_CODE ORD_DESCRIPTION
———- ———- ————— ——— ————— ————— ——————
200114 3500 2000 15-AUG-08 C00002 A008
200122 2500 400 16-SEP-08 C00003 A004
200118 500 100 20-JUL-08 C00023 A006
200119 4000 700 16-SEP-08 C00007 A010
200121 1500 600 23-SEP-08 C00008 A004
200130 2500 400 30-JUL-08 C00025 A011
200134 4200 1800 25-SEP-08 C00004 A005
200108 4000 600 15-FEB-08 C00008 A004
200103 1500 700 15-MAY-08 C00021 A005
200105 2500 500 18-JUL-08 C00025 A011
200109 3500 800 30-JUL-08 C00011 A010
200101 3000 1000 15-JUL-08 C00001 A008
200111 1000 300 10-JUL-08 C00020 A008
200104 1500 500 13-MAR-08 C00006 A004
200106 2500 700 20-APR-08 C00005 A002
200125 2000 600 10-OCT-08 C00018 A005
200117 800 200 20-OCT-08 C00014 A001
200123 500 100 16-SEP-08 C00022 A002
200120 500 100 20-JUL-08 C00009 A002
200116 500 100 13-JUL-08 C00010 A009
200124 500 100 20-JUN-08 C00017 A007
200126 500 100 24-JUN-08 C00022 A002
200129 2500 500 20-JUL-08 C00024 A006
200127 2500 400 20-JUL-08 C00015 A003
200128 3500 1500 20-JUL-08 C00009 A002
200135 2000 800 16-SEP-08 C00007 A010
200131 900 150 26-AUG-08 C00012 A012
200133 1200 400 29-JUN-08 C00009 A002
200100 1000 600 08-JAN-08 C00015 A003
200110 3000 500 15-APR-08 C00019 A010
200107 4500 900 30-AUG-08 C00007 A010
200112 2000 400 30-MAY-08 C00016 A007
200113 4000 600 10-JUN-08 C00022 A002
200102 2000 300 25-MAY-08 C00012 A012

Код SQL:

INSERT INTO neworder
SELECT * FROM  orders
WHERE advance_amount in(2000,5000);

Результат:

Подзапросы с инструкцией UPDATE

В инструкции UPDATE можно установить новое значение столбца, равное результату, возвращаемому однострочным подзапросом. Ниже приводится синтаксис и пример UPDATE с подзапросом SQL.

Синтаксис:

UPDATE таблица  SET имя_столбца = новое_значение
[ WHERE OPERATOR [ VALUE ]
(SELECT COLUMN_NAME
FROM TABLE_NAME)     
[ WHERE) ]

Если мы хотим изменить параметры ord_date в таблице ‘neworder‘ с ‘15 -JAN-10‘, для которых разница между ord_amount и advance_amount меньше минимальной ord_amount в таблице ‘orders‘,то можно использовать следующий код SQL:

Пример таблицы: neworder

ORD_NUM ORD_AMOUNT ADVANCE_AMOUNT ORD_DATE CUST_CODE AGENT_CODE ORD_DESCRIPTION
———- ———- ————— ——— ————— ————— ——————
200114 3500 2000 15-AUG-08 C00002 A008
200122 2500 400 16-SEP-08 C00003 A004
200118 500 100 20-JUL-08 C00023 A006
200119 4000 700 16-SEP-08 C00007 A010
200121 1500 600 23-SEP-08 C00008 A004
200130 2500 400 30-JUL-08 C00025 A011
200134 4200 1800 25-SEP-08 C00004 A005
200108 4000 600 15-FEB-08 C00008 A004
200103 1500 700 15-MAY-08 C00021 A005
200105 2500 500 18-JUL-08 C00025 A011
200109 3500 800 30-JUL-08 C00011 A010
200101 3000 1000 15-JUL-08 C00001 A008
200111 1000 300 10-JUL-08 C00020 A008
200104 1500 500 13-MAR-08 C00006 A004
200106 2500 700 20-APR-08 C00005 A002
200125 2000 600 10-OCT-08 C00018 A005
200117 800 200 20-OCT-08 C00014 A001
200123 500 100 16-SEP-08 C00022 A002
200120 500 100 20-JUL-08 C00009 A002
200116 500 100 13-JUL-08 C00010 A009
200124 500 100 20-JUN-08 C00017 A007
200126 500 100 24-JUN-08 C00022 A002
200129 2500 500 20-JUL-08 C00024 A006
200127 2500 400 20-JUL-08 C00015 A003
200128 3500 1500 20-JUL-08 C00009 A002
200135 2000 800 16-SEP-08 C00007 A010
200131 900 150 26-AUG-08 C00012 A012
200133 1200 400 29-JUN-08 C00009 A002
200100 1000 600 08-JAN-08 C00015 A003
200110 3000 500 15-APR-08 C00019 A010
200107 4500 900 30-AUG-08 C00007 A010
200112 2000 400 30-MAY-08 C00016 A007
200113 4000 600 10-JUN-08 C00022 A002
200102 2000 300 25-MAY-08 C00012 A012

Код SQL:

UPDATE neworder
SET ord_date='15-JAN-10'
WHERE ord_amount-advance_amount<
(SELECT MIN(ord_amount) FROM orders);

Результат:

Подзапросы с инструкцией DELETE

Ниже приводится синтаксис и пример использования SQL подзапросов с инструкцией DELETE.

Синтаксис:

DELETE FROM TABLE_NAME
[ WHERE OPERATOR [ VALUE ]
(SELECT COLUMN_NAME    
FROM TABLE_NAME)    
[ WHERE) ]

Если нужно удалить заказы из таблицы «neworder», для которых advance_amount меньше максимального значения advance_amount из таблицы «orders», можно использовать следующий код SQL:

Пример таблицы: neworder

ORD_NUM ORD_AMOUNT ADVANCE_AMOUNT ORD_DATE CUST_CODE AGENT_CODE ORD_DESCRIPTION
———- ———- ————— ——— ————— ————— ——————
200114 3500 2000 15-AUG-08 C00002 A008
200122 2500 400 16-SEP-08 C00003 A004
200118 500 100 20-JUL-08 C00023 A006
200119 4000 700 16-SEP-08 C00007 A010
200121 1500 600 23-SEP-08 C00008 A004
200130 2500 400 30-JUL-08 C00025 A011
200134 4200 1800 25-SEP-08 C00004 A005
200108 4000 600 15-FEB-08 C00008 A004
200103 1500 700 15-MAY-08 C00021 A005
200105 2500 500 18-JUL-08 C00025 A011
200109 3500 800 30-JUL-08 C00011 A010
200101 3000 1000 15-JUL-08 C00001 A008
200111 1000 300 10-JUL-08 C00020 A008
200104 1500 500 13-MAR-08 C00006 A004
200106 2500 700 20-APR-08 C00005 A002
200125 2000 600 10-OCT-08 C00018 A005
200117 800 200 20-OCT-08 C00014 A001
200123 500 100 16-SEP-08 C00022 A002
200120 500 100 20-JUL-08 C00009 A002
200116 500 100 13-JUL-08 C00010 A009
200124 500 100 20-JUN-08 C00017 A007
200126 500 100 24-JUN-08 C00022 A002
200129 2500 500 20-JUL-08 C00024 A006
200127 2500 400 20-JUL-08 C00015 A003
200128 3500 1500 20-JUL-08 C00009 A002
200135 2000 800 16-SEP-08 C00007 A010
200131 900 150 26-AUG-08 C00012 A012
200133 1200 400 29-JUN-08 C00009 A002
200100 1000 600 08-JAN-08 C00015 A003
200110 3000 500 15-APR-08 C00019 A010
200107 4500 900 30-AUG-08 C00007 A010
200112 2000 400 30-MAY-08 C00016 A007
200113 4000 600 10-JUN-08 C00022 A002
200102 2000 300 25-MAY-08 C00012 A012

Код SQL:

DELETE FROM neworder
WHERE advance_amount<
(SELECT MAX(advance_amount) FROM orders);

Результат:

Данная публикация представляет собой перевод статьи «SQL Subqueries» , подготовленной дружной командой проекта Интернет-технологии.ру