MySQL Подзаявка с примери

⚡ Умно обобщение

MySQL Синтаксисът на подзаявките поставя един SELECT оператор в друг, така че вътрешният резултат захранва външната заявка. Това обяснение обхваща скаларни, редови и таблични подзаявки, реда на изпълнение, практически примери и компромиса в производителността спрямо JOIN операциите.

  • 🔍 Основна дефиниция: Подзаявката е SELECT оператор, вложен в друга заявка, като вътрешната заявка се изпълнява първа, за да предостави стойности на външната заявка.
  • 🧮 Скаларна подзаявка: Връща един ред и една колона, така че се сдвоява с оператори за сравнение, като например равно, по-голямо от или по-малко от.
  • 📋 Подзаявки за редове и таблици: Подзаявката за ред връща един ред с няколко колони, докато подзаявката за таблица връща много редове и работи с оператора IN.
  • 🧩 Дълбочина на вмъкване: Подзаявките могат да бъдат вложени на няколко нива, което локализира стойности като например най-високоплатения член в едно изявление.
  • ✍️ Отвъд SELECT: Изразите INSERT, UPDATE и DELETE приемат подзаявки, което прави възможни групови промени без временни таблици.
  • ⚡ Правило за изпълнение: JOIN обикновено се изпълнява много по-бързо от еквивалентна подзаявка, така че резервирайте подзаявки за логика, която JOIN не може да изрази.

MySQL Подзаявка

Какво е подзаявка в SQL?

A подзаявка е SELECT заявка, която се съдържа в друга заявка. Вътрешната SELECT заявка обикновено се използва за определяне на резултатите от външната 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 с подзаявка. Същата идея премахва редове, които отговарят на условие, съдържащо се във втора таблица.

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

⚠️ Предупреждение: MySQL не позволява оператор да променя таблица и да избира от същата таблица в подзаявка в клаузата FROM. Ако се появи грешка 1093, обвийте вътрешната заявка в производна таблица, например SELECT * FROM (SELECT ...) AS t, Така че MySQL материализира резултата, преди промяната да бъде приложена. Също така е разумно първо да се изпълни вътрешният SELECT самостоятелно и да се потвърди броят на редовете, преди да се изпълни АКТУАЛИЗАЦИЯ или ИЗТРИЙ в производството.

Подзаявки срещу съединения

Както подзаявката, така и JOIN могат да комбинират информация от повече от една таблица, така че естественият въпрос е коя да изберете.

В сравнение със съединенията, подзаявките са лесни за използване и четене. Те не са толкова сложни, колкото Се присъедини къми следователно те често се използват от SQL начинаещи.

Но подзаявките имат проблеми с производителността. Използването на join вместо подзаявка понякога може да ви даде до 500 пъти по-висока производителност, защото оптимизаторът може да разреши join наведнъж, вместо да оценява вътрешния оператор многократно.

Точка на сравнение Подзаявка ПРИСЪЕДИНЕТЕ СЕ КЪМ
Четливост Високо, тъй като всеки блок отговаря на един въпрос По-ниско, тъй като всички таблици се появяват в едно изречение
Изпълнение По-бавно, вътрешната заявка може да се изпълни за всеки външен ред По-бързо, често с много голяма разлика
Колони с резултати Връщат се само колони от външната таблица Колоните от всяка присъединена таблица могат да бъдат върнати
Типична употреба Филтриране по стойност, която трябва да се изчисли първо Комбиниране на свързани редове от две или повече таблици
Крива на обучение Нежен, познат на начинаещи По-стръмно, изисква познаване на типовете съединения

При избор се препоръчва използването на JOIN над подзаявка. Подзаявките трябва да се използват само като резервно решение, когато не можете да използвате операция JOIN, за да постигнете горното.

Подзаявки срещу съединявания

Подзаявките също така лесно се разделят на отделни логически компоненти, което е много полезно, когато тестване и отстраняване на грешки в заявките.

Въпроси и Отговори

Корелираната подзаявка се отнася до колона от външната заявка, така че тя се оценява веднъж за всеки външен ред. Некорелираната подзаявка е независима и се изпълнява само веднъж. Корелираните подзаявки са мощни, но забележимо по-бавни при големи таблици.

Подзаявката може да се намира в клаузата WHERE, клаузата HAVING, списъка SELECT или клаузата FROM, където се превръща в производна таблица и изисква псевдоним. Тя е валидна и в оператори INSERT, UPDATE и DELETE.

Често, да. Асистенти с изкуствен интелект, вградени в редактори, като например MySQL Workbench може да предложи еквивалент ПРИСЪЕДИНЕТЕ СЕ КЪМВинаги сравнявайте броя на редовете и четете плана EXPLAIN, преди да се доверите на пренаписването, защото обработката на NULL може да се различава.

Да. Асистентите за текст към SQL превръщат въпрос като „коя категория има най-малко филми“ във вложен SELECT. Точността зависи от схемата, предоставена на модела, така че прегледайте генерирания оператор спрямо реалните имена на таблици.

Грешката се появява, когато подзаявка, поставена след оператор за сравнение, върне няколко реда. Заменете оператора с IN, ANY или EXISTS или стеснете вътрешната клауза WHERE, така че да се връща само един ред.

Обобщете тази публикация с: