podzapytanie to zapytanie SQL (Structured Query Language), które jest zagnieżdżone w innym zapytaniu SQL. Polecenie, w którym podzapytanie jest zagnieżdżone, jest nazywane zapytaniem nadrzędnym. Podzapytania służą do wstępnego przetwarzania danych używanych w zapytaniu nadrzędnym. Podzapytania można zastosować w SELECT
, INSERT
, UPDATE
i DELETE
operacje.
Gdy wykonywane są podzapytania, podzapytanie jest przetwarzane jako pierwsze przed zapytaniem nadrzędnym. Podczas tworzenia aplikacji MySQL korzystanie z podzapytań ma kilka zalet:
- Rozbijają instrukcje SQL na proste jednostki logiczne, co ułatwia ich zrozumienie i utrzymanie. Innymi słowy, podzapytania pomagają izolować złożone części zapytań.
- Eliminują potrzebę używania złożonej
UNION
oświadczenia iJOIN
oświadczenia. - Są one używane do wymuszania integralności referencyjnej w scenariuszu, w którym klucze obce nie są zaimplementowane.
- Pomagają programistom kodować logikę biznesową w zapytaniach MySQL.
Z tego przewodnika dowiesz się:
- Jak używać skorelowanego podzapytania
- Jak używać skorelowanego podzapytania w operatorze porównania
- Jak używać podzapytania jako tabeli pochodnej
Zanim zaczniesz
Aby postępować zgodnie z tym przewodnikiem, upewnij się, że masz następujące elementy:
-
Jeśli jeszcze tego nie zrobiłeś, utwórz konto Linode i instancję obliczeniową. Zobacz nasze przewodniki Wprowadzenie do Linode i tworzenie instancji obliczeniowej.
-
Postępuj zgodnie z naszym przewodnikiem Konfigurowanie i zabezpieczanie instancji Compute, aby zaktualizować system. Możesz także ustawić strefę czasową, skonfigurować nazwę hosta, utworzyć ograniczone konto użytkownika i utwardzić dostęp SSH.
-
Oprogramowanie serwera MySQL (lub MariaDB) zainstalowane na twoim Linode. Zapoznaj się z sekcją MySQL, która zawiera przewodniki opisujące, jak zainstalować MySQL w kilku dystrybucjach Linuksa.
Konfiguracja bazy danych
Aby zrozumieć, jak działają podzapytania, najpierw utwórz przykładową bazę danych. Ta przykładowa baza danych służy do uruchamiania różnych przykładowych zapytań w tym przewodniku:
-
SSH
na swój serwer i zaloguj się do MySQL jako root:mysql -u root -p
Po wyświetleniu monitu wprowadź hasło roota serwera MySQL i naciśnij Enter kontynuować. Pamiętaj, że hasło roota twojego serwera MySQL nie jest takie samo jak hasło roota dla twojego Linode.
Uwaga
Jeśli twoje hasło nie zostanie zaakceptowane, być może będziesz musiał uruchomić poprzednie polecenie z
sudo
:sudo mysql -u root -p
-
Jeśli Twoje hasło zostało zaakceptowane, powinieneś zobaczyć monit MySQL:
mysql >
Uwaga
Jeśli korzystasz z MariaDB, zamiast tego możesz zobaczyć monit podobny do następującego:
MariaDB [(none)]>
-
Aby utworzyć przykładową bazę danych o nazwie
test_db
, uruchom:CREATE DATABASE test_db;
Powinieneś zobaczyć ten wynik, który potwierdza, że baza danych została pomyślnie utworzona:
Query OK, 1 row affected (0.01 sec)
-
Przejdź do
test_db
baza danych:USE test_db;
Powinieneś zobaczyć to wyjście:
Database changed
-
Utworzyłeś
test_db
i wybrałem go. Następnie utwórz tabelę o nazwiecustomers
:CREATE TABLE customers ( customer_id BIGINT PRIMARY KEY AUTO_INCREMENT, customer_name VARCHAR(50) ) ENGINE = InnoDB;
Powinieneś zobaczyć to wyjście:
Query OK, 0 rows affected (0.03 sec)
-
Dodaj kilka rekordów do
customers
stół. Uruchom poniższyINSERT
polecenia jeden po drugim:INSERT INTO customers(customer_name) VALUES ('JOHN PAUL'); INSERT INTO customers(customer_name) VALUES ('PETER DOE'); INSERT INTO customers(customer_name) VALUES ('MARY DOE'); INSERT INTO customers(customer_name) VALUES ('CHRISTINE JAMES'); INSERT INTO customers(customer_name) VALUES ('MARK WELL'); INSERT INTO customers(customer_name) VALUES ('FRANK BRIAN');
To wyjście jest wyświetlane po wstawieniu każdego rekordu:
Query OK, 1 row affected (0.00 sec) ...
-
Sprawdź, czy informacje o klientach zostały wprowadzone do bazy danych. Wykonaj ten
SELECT
polecenie:SELECT * FROM customers;
Powinieneś zobaczyć tę listę klientów:
+-------------+-----------------+ | customer_id | customer_name | +-------------+-----------------+ | 1 | JOHN PAUL | | 2 | PETER DOE | | 3 | MARY DOE | | 4 | CHRISTINE JAMES | | 5 | MARK WELL | | 6 | FRANK BRIAN | +-------------+-----------------+ 6 rows in set (0.00 sec)
-
Utwórz
sales
stół. Ta tabela używa kolumnycustomer_id
odwoływanie się docustomers
tabela:CREATE TABLE sales ( order_id BIGINT PRIMARY KEY AUTO_INCREMENT, customer_id BIGINT, sales_amount DECIMAL(17,2) ) ENGINE = InnoDB;
Pojawia się to wyjście:
Query OK, 0 rows affected (0.03 sec)
-
Następnie wypełnij
sales
tabela z kilkoma rekordami. Uruchom poniższyINSERT
polecenia jeden po drugim:INSERT INTO sales (customer_id, sales_amount) VALUES ('1','25.75'); INSERT INTO sales (customer_id, sales_amount) VALUES ('2','85.25'); INSERT INTO sales (customer_id, sales_amount) VALUES ('5','3.25'); INSERT INTO sales (customer_id, sales_amount) VALUES ('4','200.75'); INSERT INTO sales (customer_id, sales_amount) VALUES ('5','88.10'); INSERT INTO sales (customer_id, sales_amount) VALUES ('1','100.00'); INSERT INTO sales (customer_id, sales_amount) VALUES ('2','45.00'); INSERT INTO sales (customer_id, sales_amount) VALUES ('4','15.80');
To wyjście jest wyświetlane po wstawieniu każdego rekordu:
Query OK, 1 row affected (0.01 sec) ...
-
Zweryfikuj dane w
sales
stół. Wykonaj tenSELECT
polecenie:SELECT * FROM sales;
Ta lista danych sprzedaży powinna się teraz wyświetlić:
+----------+-------------+--------------+ | order_id | customer_id | sales_amount | +----------+-------------+--------------+ | 1 | 1 | 25.75 | | 2 | 2 | 85.25 | | 3 | 5 | 3.25 | | 4 | 4 | 200.75 | | 5 | 5 | 88.10 | | 6 | 1 | 100.00 | | 7 | 2 | 45.00 | | 8 | 4 | 15.80 | +----------+-------------+--------------+ 8 rows in set (0.00 sec)
Po skonfigurowaniu bazy danych i powiązanych tabel możesz teraz zaimplementować różne podzapytania w MySQL.
Jak używać skorelowanego podzapytania
Skorelowane podzapytanie to typ zagnieżdżonego zapytania, które używa wartości z zapytania nadrzędnego. Tego rodzaju zapytania odwołują się do zapytania nadrzędnego za pomocą kolumny. Zapytanie zagnieżdżone jest wykonywane raz dla każdego wiersza w zapytaniu nadrzędnym.
Poniższy przykład przedstawia zapytanie, które wybiera wszystkich klientów. Wewnątrz zapytania znajduje się skorelowane podzapytanie, które pobiera całkowitą kwotę sprzedaży dla każdego klienta z sales
tabela.
-
Uruchom przykładowe zapytanie:
SELECT customer_id, customer_name, (SELECT SUM(sales_amount) FROM sales WHERE customer_id = customers.customer_id) as total_sales_amount FROM customers;
W tym przykładzie podzapytanie to
SELECT SUM(sales_amount) FROM sales WHERE customer_id = customers.customer_id
, który pojawia się w nawiasach.Pojawi się lista całkowitej sprzedaży dokonanej przez klientów:
+-------------+-----------------+--------------------+ | customer_id | customer_name | total_sales_amount | +-------------+-----------------+--------------------+ | 1 | JOHN PAUL | 125.75 | | 2 | PETER DOE | 130.25 | | 3 | MARY DOE | NULL | | 4 | CHRISTINE JAMES | 216.55 | | 5 | MARK WELL | 91.35 | | 6 | FRANK BRIAN | NULL | +-------------+-----------------+--------------------+ 6 rows in set (0.00 sec)
Powyższe dane wyjściowe ze skorelowanego podzapytania mogą dostarczyć podsumowaną listę zamówień klientów. Pamiętaj, ponieważ
customer_id
s3
i6
nie mają żadnych powiązanych rekordów w tabeli sprzedaży, ichtotal_sales_amount
jestNULL
. -
Bardziej eleganckim sposobem przedstawienia tej listy jest zwrócenie
0
zamiastNULL
dla klientów z zerową sprzedażą. Aby to zrobić, umieść dane wyjściowe wygenerowane przez podzapytanie wIFNULL(expression, 0)
oświadczenie. Uruchom to zaktualizowane polecenie:SELECT customer_id, customer_name, IFNULL((SELECT SUM(sales_amount) FROM sales WHERE customer_id = customers.customer_id), 0) as total_sales_amount FROM customers;
Pojawią się następujące dane wyjściowe. MySQL zwraca 0.00 dla wszystkich wierszy, które w przeciwnym razie zwróciłyby
NULL
wartości.+-------------+-----------------+--------------------+ | customer_id | customer_name | total_sales_amount | +-------------+-----------------+--------------------+ | 1 | JOHN PAUL | 125.75 | | 2 | PETER DOE | 130.25 | | 3 | MARY DOE | 0.00 | | 4 | CHRISTINE JAMES | 216.55 | | 5 | MARK WELL | 91.35 | | 6 | FRANK BRIAN | 0.00 | +-------------+-----------------+--------------------+ 6 rows in set (0.00 sec)
Takie podejście pomaga zapewnić, że dane wyjściowe nie zaszkodzą dalszym obliczeniom w rekordach.
Jak używać skorelowanego podzapytania w operatorze porównania
Podzapytania są przydatne do przenoszenia logiki biznesowej na poziom zapytań bazy danych. Następujące biznesowe przypadki użycia zawierają skorelowane podzapytania umieszczone wewnątrz klauzuli WHERE zapytania nadrzędnego:
-
Rozważ scenariusz, w którym chciałbyś otrzymać listę wszystkich klientów zarejestrowanych w bazie danych, którzy nie mają powiązanej sprzedaży. Możesz użyć podzapytania razem z operatorem porównania MySQL
NOT IN
i pobierz tych klientów:SELECT customer_id, customer_name FROM customers WHERE customer_id NOT IN (SELECT customer_id FROM sales);
W tym przykładzie podzapytanie to
SELECT customer_id FROM sales
, który pojawia się w nawiasach. Powyższe polecenie SQL wyświetla listę dwóch klientów, których nie ma w tabeli sprzedaży:+-------------+---------------+ | customer_id | customer_name | +-------------+---------------+ | 3 | MARY DOE | | 6 | FRANK BRIAN | +-------------+---------------+ 2 rows in set (0.00 sec)
W środowisku produkcyjnym tego rodzaju zestawu rekordów można używać do podejmowania lepszych decyzji biznesowych. Na przykład możesz utworzyć skrypt w innym języku, takim jak PHP lub Python, aby wysłać wiadomość e-mail do tych klientów i zapytać, czy mają problem ze złożeniem zamówienia.
-
Innym przypadkiem użycia jest czyszczenie danych. Na przykład możesz użyć podzapytania, aby usunąć klientów, którzy nigdy nie złożyli zamówienia:
DELETE FROM customers WHERE customer_id NOT IN (SELECT customer_id FROM sales);
Powyższe polecenie SQL usuwa dwóch klientów i wyświetla następujące informacje:
Query OK, 2 rows affected (0.01 sec)
Jeśli ponownie wykonasz polecenie, aby wyświetlić listę wszystkich klientów, ci klienci nie powinni już pojawiać się w tabeli:
SELECT * FROM customers;
Poniższe dane wyjściowe potwierdzają, że klienci bez powiązanych zamówień zostali usunięci:
+-------------+-----------------+ | customer_id | customer_name | +-------------+-----------------+ | 1 | JOHN PAUL | | 2 | PETER DOE | | 4 | CHRISTINE JAMES | | 5 | MARK WELL | +-------------+-----------------+ 4 rows in set (0.00 sec)
Jak używać podzapytania jako tabeli pochodnej
Gdy podzapytania są używane w FROM
klauzuli zapytania nadrzędnego, są one określane jako tabele pochodne . Są one bardzo ważne przy implementacji złożonych zapytań, które w innym przypadku wymagałyby MySQL VIEW
, JOIN
lub UNION
klauzula. Tabela pochodna istnieje w zapytaniu, które ją utworzyło i nie jest trwale zapisana w bazie danych.
Gdy podzapytania są używane jako tabele pochodne, izolują one różne części instrukcji SQL. Innymi słowy, podzapytanie zapewnia uproszczone wyrażenie tabeli, której można użyć w zakresie zapytania nadrzędnego.
Uwaga Pamiętaj, że każda tabela pochodna musi mieć alias.
Uruchom poniższe polecenie, aby utworzyć podzapytanie tabeli pochodnej o aliasie order_summary
:
SELECT customer_id
FROM
(
SELECT
customer_id,
count(order_id) as total_orders
FROM sales
group by customer_id
) as order_summary
WHERE order_summary.total_orders > 1;
UwagaW tym poleceniu podzapytanie pojawia się w nawiasach jako:
SELECT customer_id, count(order_id) as total_orders FROM sales group by customer_id
Powyższe polecenie wysyła zapytanie do tabeli sprzedaży, aby określić klientów z więcej niż 1 zamówieniem. Po uruchomieniu zapytania pojawia się następujący wynik:
+-------------+
| customer_id |
+-------------+
| 1 |
| 2 |
| 5 |
| 4 |
+-------------+
4 rows in set (0.00 sec)
Powyższa lista zawiera cztery customer_id
s, które mają więcej niż jedno zamówienie. Jako przykład biznesowego przypadku użycia, możesz użyć takiego zapytania w skrypcie, który nagradza klientów premią przy następnym zakupie.
Więcej informacji
Dodatkowe informacje na ten temat można znaleźć w poniższych zasobach. Chociaż są one dostarczane w nadziei, że będą przydatne, należy pamiętać, że nie możemy ręczyć za dokładność ani aktualność materiałów hostowanych zewnętrznie.
- Podzapytania MySQL