Подзапросы SQL

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

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

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

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

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

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

Синтаксис:

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

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

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

student

студенты

marks

отметки

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

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

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

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

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

student-query

Результатом запроса будет 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;

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

student-marks-query

Два приведенных запроса определяют студентов, которые получают лучше оценки, чем студент 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');

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

student-marks-query

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

sql-subqueries

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

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

Синтаксис:

(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);

Результат:

insert-output

Подзапросы с инструкцией 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);

Результат:

update-output

Подзапросы с инструкцией 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);

Результат:

delete-output

Перевод статьи «SQL Subqueries» дружной командой проекта Сайтостроение от А до Я.

01 октября 2017 в 11:40
Материалы по теме
{"url":"http://www.fastvps.ru/", "src":"/images/advbanners/fastvps.png", "alt":"Хостинг Fastvps.ru. Наш выбор!"}
Заработок