MySQL Podupit s primjerima

⚡ Pametni sažetak

MySQL Sintaksa podupita smješta jednu SELECT naredbu unutar druge, tako da unutarnji rezultat daje vanjski upit. Ovo objašnjenje pokriva skalarne, redne i tablične podupite, redoslijed izvršavanja, praktične primjere i kompromis u performansama u odnosu na JOIN operacije.

  • 🔍 Osnovna definicija: Podupit je SELECT naredba ugniježđena unutar drugog upita, a unutarnji upit se izvršava prvi kako bi dostavio vrijednosti vanjskom upitu.
  • 🧮 Skalarni podupit: Vraća jedan redak i jedan stupac, pa se uparuje s operatorima usporedbe kao što su jednako, veće od ili manje od.
  • 📋 Podupiti redaka i tablice: Podupit retka vraća jedan redak s nekoliko stupaca, dok podupit tablice vraća mnogo redaka i radi s operatorom IN.
  • 🧩 Dubina ugniježđivanja: Podupiti mogu biti ugniježđeni na nekoliko razina duboko, što locira vrijednosti poput člana koji najviše plaća u jednoj izjavi.
  • ✍️ Iza SELECT-a: Naredbe INSERT, UPDATE i DELETE prihvaćaju podupite, što omogućuje skupne promjene bez privremenih tablica.
  • ⚡ Pravilo izvedbe: JOIN se obično izvršava puno brže od ekvivalentnog podupita, stoga rezervirajte podupite za logiku koju JOIN ne može izraziti.

MySQL Podupit

Što je podupit u SQL-u?

A podupit je SELECT upit koji se nalazi unutar drugog upita. Unutarnji SELECT upit obično se koristi za određivanje rezultata vanjskog SELECT upita, pa baza podataka prvo procjenjuje unutarnju naredbu, a zatim prosljeđuje njezin izlaz prema gore.

Unutarnji upit se naziva unutarnji upit ili ugniježđeni upit, a naredba koja ga sadrži naziva se vanjski upitPogledajmo sintaksu podupita.

MySQL Podupit

Gornji dijagram prikazuje opći oblik naredbe: vanjski SELECT daje stupce koje želite vidjeti, a unutarnji SELECT u zagradama daje vrijednost ili popis vrijednosti s kojima se klauzula WHERE uspoređuje.

Zašto koristiti podupit?

Prije nego što pogledamo različite tipove, korisno je znati kada podupit zaslužuje svoje mjesto u izrazu.

Podupit odgovara na pitanje čija vrijednost filtera nije unaprijed poznata. Mora se izračunati iz samih podataka. Uobičajena pritužba kupaca u MyFlix videoteci je mali broj naslova filmova, a uprava želi kupiti filmove za kategoriju koja ima najmanji broj naslova. Nitko ne zna koja je to kategorija dok se ne zatraži od baze podataka, pa se vrijednost prvo mora izračunati, a zatim koristiti kao filter.

Podupiti su natraciz tri praktična razloga:

  • Čitljivost: Svaki dio logike nalazi se u vlastitom bloku u zagradama, pa se izjava čita kao niz malih pitanja, a ne kao jedan složeni izraz.
  • Izolacija: Unutarnji upit može se pokrenuti samostalno kako bi se potvrdilo da vraća očekivanu vrijednost, što znatno olakšava testiranje i otklanjanje pogrešaka.
  • Fleksibilnost: Isti obrazac funkcionira u klauzulama WHERE, HAVING, SELECT i FROM, kao i unutar naredbi INSERT, UPDATE i DELETE.

Kompromis je brzina, što se ispituje u usporedbi JOIN-a kasnije u ovom članku.

Vrste podupita u MySQL

MySQL podržava tri vrste podupita, a vrsta se određuje oblikom rezultata koji vraća unutarnji upit. Svaka vrsta je objašnjena u nastavku s radnim primjerom na bazi podataka myflixdb.

1) Skalarni podupit

A skalarni podupit vraća točno jedan redak i jedan stupac, što znači da vraća jednu vrijednost. Budući da je rezultat jedna vrijednost, može se koristiti bilo gdje gdje je dopuštena doslovna vrijednost. Vraćajući se na gornji problem MyFlix, možete koristiti upit poput ovog:

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

Daje rezultat:

MySQL Podupit

Pogledajmo kako ovaj upit funkcionira.

MySQL Podupit

Kao što dijagram izvršenja pokazuje, MySQL prve vožnje SELECT MIN(category_id) FROM movies, prima jednu vrijednost i tek tada pokreće vanjski upit s tom vrijednošću. Budući da se vraća jedna vrijednost, dopušteni operatori su standardni skup usporedbi: =, <> (Ili !=), >, >=, <i <=.

💡 Savjet: Ako se podupit postavi nakon = vraća više od jednog reda, MySQL javlja grešku 1242, Podupit vraća više od 1 retkaPrebacite operatora na INili skratite unutarnju klauzulu WHERE.

2) Podupit retka

A podupit retka također vraća jedan redak, ali taj redak može sadržavati više od jednog stupca. Vanjski upit stoga uspoređuje redak vrijednosti s konstruktorom retka, a ne s jednom vrijednošću.

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

Dopušteni operatori su isti operatori usporedbe navedeni gore, primijenjeni na cijeli redak odjednom.

3) Podupit tablice

A podupit tablice vraća više redaka, a često i više stupaca, pa vanjski upit mora koristiti operator skupa kao što je IN, NOT IN, ANY, ALL, ili EXISTS.

Pretpostavimo da želite imena i brojeve telefona članova koji su posudili film i još ga nisu vratili, kako biste ih mogli pozvati i podsjetiti. Možete koristiti upit poput ovog:

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

MySQL Podupit

Pogledajmo kako ovaj upit funkcionira.

MySQL Podupit

U ovom slučaju, unutarnji upit vraća više od jednog rezultata, pa se popis brojeva članstva predaje IN operator i vraća se svaki odgovarajući član.

Ugniježđivanje podupita na nekoliko razina dubine

Do sada ste vidjeli dvije razine. Podupit može sadržavati i drugi podupit, koji proizvodi trostruko ugniježđenu naredbu.

Pretpostavimo da uprava želi nagraditi člana koji najviše plaća. Možemo pokrenuti upit poput ovog:

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

Unutarnji upit pronalazi najveću uplatu, srednji upit pretvara taj iznos u članski broj, a vanjski upit pretvara članski broj u ime. Gornji upit daje sljedeći rezultat:

MySQL Podupit

Kako koristiti podupite s INSERT, UPDATE i DELETE

Podupiti nisu ograničeni na SELECT naredbe. Isti obrazac u zagradama funkcionira unutar naredbi za modifikaciju podataka, što omogućuje promjenu cijelog skupa redaka u jednom prolazu bez stvaranja privremene tablice.

INSERT s podupitorom. Podupit može navesti retke koji se umeću, što kopira podatke iz jedne tablice u drugu. Popis stupaca naredbe SELECT mora se poravnati s popisom stupaca naredbe 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);

AŽURIRANJE s podupitorom. Ovdje unutarnji upit odlučuje koji će se retci dotaknuti. Primjer u nastavku označava svakog člana čiji je najam još uvijek nepodmiren.

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

IZBRIŠI s podupitorom. Ista ideja uklanja retke koji zadovoljavaju uvjet sadržan u drugoj tablici.

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

⚠️ Upozorenje: MySQL ne dopušta naredbi da modificira tablicu i odabire iz iste tablice unutar podupita u FROM klauzuli. Ako se pojavi greška 1093, unutarnji upit omotajte u izvedenu tablicu, na primjer SELECT * FROM (SELECT ...) AS t, Tako da MySQL materijalizira rezultat prije nego što se promjena primijeni. Također je mudro prvo pokrenuti unutarnji SELECT samostalno i potvrditi broj redaka prije pokretanja UPDATE ili DELETE u proizvodnji.

Podupiti u odnosu na spajanja

I podupit i JOIN mogu kombinirati informacije iz više tablica, pa se prirodno postavlja pitanje koju odabrati.

U usporedbi sa spajanjima, podupiti su jednostavni za korištenje i lako ih je čitati. Nisu toliko komplicirani kao Pridružuje, i stoga ih često koriste SQL početnici.

Ali podupiti imaju problema s performansama. Korištenje spajanja umjesto podupita ponekad može dati poboljšanje performansi i do 500 puta, jer optimizator može riješiti spajanje u jednom prolazu umjesto da više puta procjenjuje unutarnju naredbu.

Točka usporedbe Podupit PRIDRUŽITE
čitljivost Visoko, jer svaki blok odgovara na jedno pitanje Niže, jer se sve tablice pojavljuju u jednoj klauzuli
Izvođenje Sporije, unutarnji upit može se izvršavati za svaki vanjski redak Brže, često s vrlo velikom razlikom
Stupci rezultata Vraćaju se samo stupci vanjske tablice Mogu se vratiti stupci iz svake spojene tablice
Tipična upotreba Filtriranje po vrijednosti koja se prvo mora izračunati Kombiniranje povezanih redaka iz dvije ili više tablica
Krivulja ucenja Nježno, poznato početnicima Strmiji, zahtijeva poznavanje vrsta spojeva

Ako imate izbor, preporuča se koristiti JOIN preko pod upita. Podupite treba koristiti samo kao rezervno rješenje kada ne možete koristiti JOIN operaciju za postizanje gore navedenog.

Podupiti protiv spajanja

Podupite je također lako razložiti na pojedinačne logičke komponente, što je vrlo korisno kada testiranje i otklanjanje pogrešaka u upitima.

Pitanja i odgovori

Korelirani podupit odnosi se na stupac vanjskog upita, pa se procjenjuje jednom za svaki vanjski redak. Nekorelirani podupit je neovisan i izvršava se samo jednom. Korelirani podupiti su moćni, ali primjetno sporiji na velikim tablicama.

Podupit se može nalaziti u klauzuli WHERE, klauzuli HAVING, listi SELECT ili klauzuli FROM, gdje postaje izvedena tablica i zahtijeva alias. Također je valjan unutar naredbi INSERT, UPDATE i DELETE.

Često, da. AI asistenti ugrađeni u urednike kao što su MySQL Radna tezga može predložiti ekvivalent PRIDRUŽITEUvijek usporedite broj redaka i pročitajte EXPLAIN plan prije nego što povjerujete prepisivanju, jer se rukovanje NULL vrijednostima može razlikovati.

Da. Pomoćnici za pretvorbu teksta u SQL pretvaraju pitanje poput „koja kategorija ima najmanje filmova“ u ugniježđeni SELECT. Točnost ovisi o shemi koja je dostavljena modelu, stoga usporedite generiranu naredbu sa stvarnim nazivima tablica.

Greška se pojavljuje kada podupit postavljen nakon operatora usporedbe vrati nekoliko redaka. Zamijenite operator s IN, ANY ili EXISTS ili suzite unutarnju klauzulu WHERE tako da se vraća samo jedan redak.

Sažmite ovu objavu uz: