MySQL Підзапит із прикладами

⚡ Розумний підсумок

MySQL Синтаксис підзапитів розміщує один оператор SELECT всередині іншого, тому внутрішній результат передає зовнішній запит. Це пояснення охоплює скалярні, рядкові та табличні підзапити, порядок виконання, практичні приклади та компроміс у продуктивності порівняно з операціями JOIN.

  • 🔍 Основне визначення: Підзапит — це оператор SELECT, вкладений всередину іншого запиту, причому внутрішній запит виконується першим, щоб надати значення зовнішньому запиту.
  • 🧮 Скалярний підзапит: Повертає один рядок та один стовпець, тому він поєднується з операторами порівняння, такими як «дорівнює», «більше ніж» або «менше ніж».
  • 📋 Підзапити рядків і таблиць: Підзапит рядка повертає один рядок з кількома стовпцями, тоді як підзапит таблиці повертає багато рядків і працює з оператором IN.
  • 🧩 Глибина вкладення: Підзапити можуть бути вкладені на кілька рівнів, що дозволяє знаходити такі значення, як найвище платіжний учасник, в одному операторі.
  • ✍️ Окрім SELECT: Оператори INSERT, UPDATE та DELETE приймають підзапити, що робить можливим масове внесення змін без використання тимчасових таблиць.
  • Правило продуктивності: JOIN зазвичай виконується набагато швидше, ніж еквівалентний підзапит, тому резервуйте підзапити для логіки, яку JOIN не може виразити.

MySQL Підзапит

Що таке підзапит у SQL?

A підзапит – це запит SELECT, який міститься всередині іншого запиту. Внутрішній запит на вибір зазвичай використовується для визначення результатів зовнішнього запиту на вибір, тому база даних спочатку оцінює внутрішній оператор, а потім передає його вивід вгору.

Внутрішній запит називається внутрішній запит або вкладений запит, а оператор, що його містить, називається зовнішній запитДавайте розглянемо синтаксис підзапиту.

MySQL Підзапит

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

Навіщо використовувати підзапит?

Перш ніж розглядати різні типи, корисно знати, коли підзапит заслуговує на своє місце в операторі.

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

Підзапити знаходяться за адресоюtracтивний з трьох практичних причин:

  • читаність: Кожна частина логіки знаходиться у власному блоці в дужках, тому твердження читається як послідовність невеликих запитань, а не як один складний вираз.
  • Ізоляція: Внутрішній запит можна виконати окремо, щоб підтвердити, що він повертає очікуване значення, що значно спрощує тестування та налагодження.
  • Гнучкість: Той самий шаблон працює в реченнях WHERE, HAVING, SELECT та FROM, а також всередині операторів INSERT, UPDATE та DELETE.

Компромісом є швидкість, яка розглядається в порівнянні JOIN далі в цій статті.

Типи підзапитів у MySQL

MySQL підтримує три типи підзапитів, а тип визначається формою результату, який повертає внутрішній запит. Кожен тип пояснюється нижче з робочим прикладом для бази даних myflixdb.

1) Скалярний підзапит

A скалярний підзапит повертає рівно один рядок і один стовпець, тобто повертає одне значення. Оскільки результатом є одне значення, його можна використовувати будь-де, де дозволено літерне значення. Повертаючись до наведеної вище задачі MyFlix, можна використовувати запит, подібний до цього:

SELECT category_name FROM categories
WHERE category_id = (SELECT MIN(category_id) FROM movies);

Це дає результат:

MySQL Підзапит

Давайте подивимося, як працює цей запит.

MySQL Підзапит

Як видно зі схеми виконання, MySQL перші пробіжки SELECT MIN(category_id) FROM movies, отримує одне значення, і лише потім виконує зовнішній запит з цим значенням. Оскільки повертається одне значення, допустимі оператори – це стандартний набір порівняння: =, <> (Або !=), >, >=, < та <=.

💡 Порада: Якщо підзапит розміщено після = повертає більше одного рядка, MySQL викликає помилку 1242, Підзапит повертає більше 1 рядкаПереключити оператора на INабо звужте внутрішню речення WHERE.

2) Підзапит рядка

A підзапит рядка також повертає один рядок, але цей рядок може містити більше одного стовпця. Тому зовнішній запит порівнює рядок значень з конструктором рядків, а не з одним значенням.

SELECT full_names, contact_number FROM members
WHERE (membership_number, gender) = (SELECT membership_number, gender FROM members WHERE full_names = 'Janet Jones');

Допустимі оператори — це ті ж оператори порівняння, що перелічені вище, застосовані до всього рядка одночасно.

3) Підзапит до таблиці

A підзапит до таблиці повертає кілька рядків, а часто й кілька стовпців, тому зовнішній запит повинен використовувати оператор множини, такий як IN, NOT IN, ANY, ALLабо EXISTS.

Припустимо, вам потрібні імена та номери телефонів учасників, які взяли фільм напрокат і ще не повернули його, щоб ви могли зателефонувати їм і нагадати. Ви можете використати запит, подібний до цього:

SELECT full_names, contact_number FROM members
WHERE membership_number IN (SELECT membership_number FROM movierentals WHERE return_date IS NULL);

MySQL Підзапит

Давайте подивимося, як працює цей запит.

MySQL Підзапит

У цьому випадку внутрішній запит повертає більше одного результату, тому список номерів членства передається до IN оператор, і повертається кожен відповідний член.

Вкладення підзапитів на кілька рівнів глибини

Досі ви розглядали два рівні. Підзапит може також містити інший підзапит, який створює потрійний вкладений оператор.

Припустимо, що керівництво хоче винагородити найплатнішого учасника. Ми можемо виконати запит типу цього:

SELECT full_names FROM members
WHERE membership_number = (SELECT membership_number FROM payments
    WHERE amount_paid = (SELECT MAX(amount_paid) FROM payments));

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

MySQL Підзапит

Як використовувати підзапити з INSERT, UPDATE та DELETE

Підзапити не обмежуються операторами SELECT. Той самий шаблон у дужках працює всередині операторів модифікації даних, що дозволяє змінити весь набір рядків за один прохід без створення тимчасової таблиці.

INSERT з підзапитом. Підзапит може надати рядки, що вставляються, що копіює дані з однієї таблиці в іншу. Список стовпців оператора SELECT повинен збігатися зі списком стовпців оператора INSERT.

INSERT INTO vip_members (membership_number, full_names)
SELECT membership_number, full_names FROM members
WHERE membership_number IN (SELECT membership_number FROM payments WHERE amount_paid > 5000);

ОНОВЛЕННЯ за допомогою підзапиту. Тут внутрішній запит визначає, яких рядків торкатися. У наведеному нижче прикладі позначено кожного учасника, чия оренда все ще не сплачена.

UPDATE members
SET reminder_sent = 1
WHERE membership_number IN (SELECT membership_number FROM movierentals WHERE return_date IS NULL);

ВИДАЛИТИ з підзапитом. Та сама ідея видаляє рядки, які задовольняють умову, що міститься в другій таблиці.

DELETE FROM members
WHERE membership_number NOT IN (SELECT membership_number FROM movierentals);

⚠️ Попередження: MySQL не дозволяє оператору змінювати таблицю та вибирати з тієї ж таблиці всередині підзапиту в реченні FROM. Якщо з'являється помилка 1093, оберніть внутрішній запит у похідну таблицю, наприклад SELECT * FROM (SELECT ...) AS t, Так що MySQL матеріалізує результат до застосування змін. Також доцільно спочатку виконати внутрішній SELECT окремо та підтвердити кількість рядків, перш ніж запускати ОНОВЛЕННЯ або DELETE у виробництві.

Підзапити проти об'єднань

Як підзапит, так і JOIN можуть об'єднувати інформацію з кількох таблиць, тому виникає природне питання, яку з них обрати.

Порівняно з об'єднаннями, підзапити прості у використанні та легкі для читання. Вони не такі складні, як з'єднання, і тому їх часто використовують Початківці SQL.

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

Точка порівняння Підзапит РЕЄСТРАЦІЯ
читабельність Високий, оскільки кожен блок відповідає на одне питання Нижче, оскільки всі таблиці відображаються в одному реченні
продуктивність Повільніше, внутрішній запит може виконуватися для кожного зовнішнього рядка Швидше, часто з дуже великим відривом
Стовпці результатів Повертаються лише стовпці зовнішньої таблиці Стовпці з кожної об'єднаної таблиці можна повернути
Типове використання Фільтрація за значенням, яке потрібно обчислити спочатку Об'єднання пов'язаних рядків з двох або більше таблиць
Крива навчання Ніжний, знайомий новачкам Крутіший, вимагає знання типів з'єднань

За наявності вибору рекомендується використовувати JOIN замість підзапиту. Підзапити слід використовувати лише як резервне рішення, коли ви не можете використати операцію JOIN для досягнення вищезазначеного.

Підзапити проти об’єднань

Підзапити також легко розбити на окремі логічні компоненти, що дуже корисно, коли Тестування і налагодження запитів.

Поширені запитання

Корельований підзапит посилається на стовпець зовнішнього запиту, тому він обчислюється один раз для кожного зовнішнього рядка. Некорельований підзапит є незалежним і виконується лише один раз. Корельовані підзапити є потужними, але помітно повільнішими у великих таблицях.

Підзапит може знаходитися в реченні WHERE, реченні HAVING, списку SELECT або реченні FROM, де він стає похідною таблицею та потребує псевдоніма. Він також дійсний всередині інструкцій INSERT, UPDATE та DELETE.

Часто так. Вбудовані в редактори помічники зі штучним інтелектом, такі як MySQL Верстак може запропонувати еквівалент РЕЄСТРАЦІЯЗавжди порівнюйте кількість рядків і читайте план EXPLAIN, перш ніж довіряти перезапису, оскільки обробка NULL може відрізнятися.

Так. Помічники з тексту в SQL перетворюють таке запитання, як «у якій категорії найменше фільмів», на вкладений SELECT. Точність залежить від схеми, наданої моделі, тому перевірте згенерований оператор на відповідність реальним іменам таблиць.

Помилка виникає, коли підзапит, розміщений після оператора порівняння, повертає кілька рядків. Замініть оператор на IN, ANY або EXISTS, або скоротіть внутрішню речення WHERE, щоб повертався лише один рядок.

Підсумуйте цей пост за допомогою: