Подзапросы в основных командах SQL.

Подзапросы в SELECT

https://t.me/data_analysis_ml

В выражении SELECT мы можем вводить подзапросы четырьмя способами:

  1. В условии в выражении WHERE
  2. В условии в выражении HAVING
  3. В качестве таблицы для выборки в выражении FROM
  4. В качестве спецификации столбца в выражении SELECT

Рассмотрим некоторые из этих случаев. Например, получим все товары, у которых цена выше средней:

12SELECT* FROMProductsWHEREPrice > (SELECTAVG(Price) FROMProducts)

Чтобы получить нужные товары, нам вначале надо выполнить подзапрос на получение средней цены товара: SELECT AVG(Price) FROM Products.

Оператор IN

Нередко подзапросы применяются вместе с оператором IN, который выбирает из набора значений. И подзапрос как раз может предоставить требуемый набор значений. Например, выберем все товары из таблицы Products, на которые есть заказы в таблице Orders:

12SELECT* FROMProductsWHEREId IN(SELECTProductId FROMOrders)

То есть подзапрос в данном случае выбирает все идентификаторы товаров из Orders, затем по этим идентификаторам извлекаютя товары из Products.

Добавив оператор NOT, мы можем выбрать те товары, на которые нет заказов в таблице Orders:

12SELECT* FROMProductsWHEREId NOTIN(SELECTProductId FROMOrders)

Стоит отметить, что это не самый эффективный способ для извлечения связанных данных из других таблиц, так как для сведения данных из разных таблиц можно использовать оператор JOIN, который рассматривается в следующей главе.

Получение набора значений

При использовании в операторах сравнения подзапросы должны возвращать одно скалярное значение. Но иногда возникает необходимость получить набор значений. Чтобы при использовании в операторах сравнения подзапрос мог возвращать набор значений, перед ним необходимо использовать один из операторов: ALLSOME или ANY.

При использовании ключевого слова ALL условие в операции сравнения должно быть верно для всех значений, которые возвращаются подзапросом. Например, найдем все товары, цена которых меньше чем у любого товара фирмы Apple:

12SELECT* FROMProductsWHEREPrice < ALL(SELECTPrice FROMProducts WHEREManufacturer='Apple')

Если бы мы в данном случае опустили бы ключевое слово ALL, то мы бы столкнулись с ошибкой.

Допустим, если данный подзапрос возвращает значения vаl1, val2 и val3, то условие фильтрации фактически было бы аналогично объединению этих значений через оператор AND:

1WHEREPrice < val1 ANDPrice < val2 ANDPrice < val3

В тоже время подобный запрос гораздо проще переписать другим образом:

12SELECT* FROMProductsWHEREPrice < (SELECTMIN(Price) FROMProducts WHEREManufacturer='Apple')

Как работает оператор ALL:

  • x > ALL (1, 2) эквивалентно x > 2
  • x < ALL (1, 2) эквивалентно x < 1
  • x = ALL (1, 2) эквивалентно (x = 1) AND (x = 2)
  • x <> ALL (1, 2) эквивалентно x NOT IN (1, 2)

Операторы ANY и SOME условие в операции сравнения должно быть истинным для хотя бы одного из значений, возвращаемых подзапросом. По своему действию оба этих оператора аналогичны, поэтому можно применять любой из них. Например, в следующем случае получим товары, которые стоят меньше самого дорогого товара компании Apple:

12SELECT* FROMProductsWHEREPrice < ANY(SELECTPrice FROMProducts WHEREManufacturer='Apple')

И также стоит отметить, что данный запрос можно сделать проще, переписав следующим образом:

12SELECT* FROMProductsWHEREPrice < (SELECTMAX(Price) FROMProducts WHEREManufacturer='Apple')

Как работает оператор ANY (а также SOME):

  • x > ANY (1, 2) эквивалентно x > 1
  • x < ANY (1, 2) эквивалентно x < 2
  • x = ANY (1, 2) эквивалентно x IN (1, 2)
  • x <> ANY (1, 2) эквивалентно (x <> 1) OR (x <> 2)

Подзапрос как спецификация столбца

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

123SELECT*, (SELECTProductName FROMProducts WHEREId=Orders.ProductId) ASProduct FROMOrders
Подзапросы в SELECT в MySQL

Подзапросы в команде INSERT

В команде INSERT подзапросы могут применяться для определения значения, которое вставляется в один из столбцов:

12345678INSERTINTOOrders (ProductId, CreatedAt, ProductCount, Price)VALUES(     (SELECTId FROMProducts WHEREProductName='Galaxy S8'),    '2018-05-23'    2,     (SELECTPrice FROMProducts WHEREProductName='Galaxy S8'))

Подзапросы в команде UPDATE

В команде UPDATE подзапросы могут применяться:

  1. В качестве устанавливаемого значения после оператора SET
  2. Как часть условия в выражении WHERE

Так, увеличим в таблице Orders количество купленных товаров компании Apple на 2:

123UPDATEOrdersSETProductCount = ProductCount + 2WHEREProductId IN(SELECTId FROMProducts WHEREManufacturer='Apple');

Или установим для заказа цену товара, полученную в результате подзапроса:

123UPDATEOrdersSETPrice = (SELECTPrice FROMProducts WHEREId=Orders.ProductId) + 3000WHEREId=1;

Подзапросы в команде DELETE

В команде DELETE подзапросы также применяются как часть условия. Так, удалим все заказы на Galaxy S8:

12DELETEFROMOrdersWHEREProductId=(SELECTId FROMProducts WHEREProductName='Galaxy S8');

https://t.me/sqlhub

источник

Ответить