MySQL підзапити в основних командах


Підзапити в SELECT

У виразі SELECT ми можемо вводити підзапити чотирма способами:

  1. В умови в виразі WHERE

  2. В умови в виразі HAVING

  3. Як таблиці для вибірки в виразі FROM

  4. В якості специфікації стовпця в виразі SELECT

Розглянемо деякі з цих випадків. Наприклад, отримаємо усі товари, у яких ціна вище середньої:

SELECT * FROM Products
WHERE Price > (SELECT AVG(Price) FROM Products)

Щоб отримати потрібні товари, нам спочатку треба виконати підзапит на отримання середньої ціни товару:

SELECT AVG(Price) FROM Products .


Оператор IN

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

SELECT * FROM Products
WHERE Id IN (SELECT ProductId FROM Orders)

Тобто підзапит в даному випадку вибирає все ідентифікатори товарів з Orders , потім по цим ідентифікаторів витягаються товари з Products .

Додавши оператор NOT , ми можемо вибрати ті товари, на які немає замовлень в таблиці Orders :

SELECT * FROM Products
WHERE Id NOT IN (SELECT ProductId FROM Orders)

Варто відзначити, що це не найефективніший спосіб для вилучення пов'язаних даних з інших таблиць, так як для зведення даних з різних таблиць можна використовувати оператор JOIN , який розглядається в наступному розділі.


Отримання набору значень

При використанні в операторах порівняння підзапити повинні повертати одне скалярне значення. Але іноді виникає необхідність отримати набір значень. Щоб при використанні в операторах порівняння підзапит міг повертати набір значень, перед ним необхідно використовувати один з операторів: ALL , SOME або ANY .

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

SELECT * FROM Products
WHERE Price < ALL(SELECT Price FROM Products WHERE Manufacturer='Apple')

Якби ми в даному випадку опустили б ключове слово ALL , то ми б зіткнулися з помилкою.

Припустимо, якщо даний підзапит повертає значення vаl1, val2 і val3, то умова фільтрації фактично було б аналогічно об'єднанню цих значень через оператор AND :

WHERE Price < val1 AND Price < val2 AND Price < val3

У той же час подібний запит набагато простіше переписати іншим чином:

SELECT * FROM Products
WHERE Price < (SELECT MIN(Price) FROM Products WHERE Manufacturer='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:

SELECT * FROM Products 
WHERE Price < ANY(SELECT Price FROM Products WHERE Manufacturer='Apple')

І також варто відзначити, що даний запит можна зробити простіше, переписавши наступним чином:

SELECT * FROM Products
WHERE Price < (SELECT MAX(Price) FROM Products WHERE Manufacturer='Apple')

Як працює оператор ANY (а також SOME ):

  • x > ANY (1, 2) еквівалентно x > 1

  • x < ANY (1, 2) еквівалентно x < 2

  • x = ANY (1, 2) еквівалентно x NOT (1, 2)

  • x <> ANY (1, 2) еквівалентно (x <> 1) OR (x <> 2)


Підзапит як специфікація стовпця

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

SELECT *, (
SELECT ProductName FROM Products WHERE Id=Orders.ProductId) AS Product 
FROM Orders

Підзапити в команді INSERT

У команді INSERT підзапити можуть застосовуватися для визначення значення, яке вставляється в один зі стовпців:

INSERT INTO Orders (ProductId, CreatedAt, ProductCount, Price)
VALUES
(
    (SELECT Id FROM Products WHERE ProductName='Galaxy S8'),
    '2018-05-23', 
    2,
    (SELECT Price FROM Products WHERE ProductName='Galaxy S8')
)

Підзапити в команді UPDATE

У команді UPDATE підзапити можуть застосовуватися:

  1. Як встановлюється значення після оператора SET

  2. Як частина умови в вираженні WHERE

Так, збільшимо в таблиці Orders кількість куплених товарів компанії Apple на 2:

UPDATE Orders
SET ProductCount = ProductCount + 2
WHERE ProductId IN (SELECT Id FROM Products WHERE Manufacturer='Apple');

Або встановимо для замовлення ціну товару, отриману в результаті підзапиту:

UPDATE Orders
SET Price = (SELECT Price FROM Products WHERE Id=Orders.ProductId) + 3000
WHERE Id=1;

Підзапити в команді DELETE

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

DELETE FROM Orders
WHERE ProductId=(SELECT Id FROM Products WHERE ProductName='Galaxy S8');

Наш партнер:
beta test mp3 playlist downloader