подзаявка е SQL (Structured Query Language) заявка, която е вложена в друга SQL заявка. Командата, в която е вложена подзаявката, се нарича родителска заявка. Подзаявките се използват за предварителна обработка на данни, които се използват в родителската заявка. Подзаявките могат да се прилагат в SELECT , INSERT , UPDATE и DELETE операции.
Когато се изпълняват подзаявки, подзаявката се обработва първо преди родителската заявка. Когато създавате MySQL приложения, използването на подзаявки предлага няколко предимства:
- Те разбиват SQL изразите на прости логически единици, което може да ги направи по-лесни за разбиране и поддържане. С други думи, подзаявките помагат да се изолират сложни части от заявките.
- Те премахват необходимостта от използване на комплекс
UNIONизявления иJOINизявления. - Те се използват за налагане на референтна цялост в сценарий, при който не се прилагат външни ключове.
- Те помагат на разработчиците да кодират бизнес логиката в MySQL заявките.
В това ръководство ще научите:
- Как да използвате корелирана подзаявка
- Как да използвате корелирана подзаявка в оператор за сравнение
- Как да използваме подзаявка като производна таблица
Преди да започнете
За да следвате това ръководство, уверете се, че имате следното:
-
Ако все още не сте го направили, създайте акаунт в Linode и Compute Instance. Вижте нашите ръководства Първи стъпки с Linode и Създаване на изчислителен екземпляр.
-
Следвайте нашето ръководство за настройка и осигуряване на изчислителен екземпляр, за да актуализирате вашата система. Може също да пожелаете да зададете часовата зона, да конфигурирате името на хоста си, да създадете ограничен потребителски акаунт и да укрепите SSH достъпа.
-
MySQL сървърният софтуер (или MariaDB), инсталиран на вашия Linode. Моля, вижте раздела MySQL, който съдържа ръководства, които описват как да инсталирате MySQL в няколко Linux дистрибуции.
Настройване на базата данни
За да разберете как работят подзаявките, първо създайте примерна база данни. Тази примерна база данни се използва за изпълнение на различните примерни заявки в това ръководство:
-
SSHкъм вашия сървър и влезте в MySQL като root:mysql -u root -pКогато бъдете подканени, въведете root паролата на вашия MySQL сървър и натиснете Enter продължавам. Имайте предвид, че root паролата на вашия MySQL сървър не е същата като root паролата за вашия Linode.
Забележка
Ако паролата ви не е приета, може да се наложи да изпълните предишната команда с
sudo:sudo mysql -u root -p -
Ако вашата парола е приета, трябва да видите подканата за MySQL:
mysql >Забележка
Ако използвате MariaDB, вместо това може да видите подкана като следната:
MariaDB [(none)]> -
За да създадете примерна база данни с име
test_db, стартирайте:CREATE DATABASE test_db;Трябва да видите този изход, който потвърждава, че базата данни е създадена успешно:
Query OK, 1 row affected (0.01 sec) -
Превключете към
test_dbбаза данни:USE test_db;Трябва да видите този изход:
Database changed -
Създадохте
test_dbи го избра. След това създайте таблица с имеcustomers:CREATE TABLE customers ( customer_id BIGINT PRIMARY KEY AUTO_INCREMENT, customer_name VARCHAR(50) ) ENGINE = InnoDB;Трябва да видите този изход:
Query OK, 0 rows affected (0.03 sec) -
Добавете някои записи към
customersмаса. Изпълнете долнияINSERTкоманди една по една: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');Този изход се показва след вмъкване на всеки запис:
Query OK, 1 row affected (0.00 sec) ... -
Проверете дали информацията за клиентите е вмъкната в базата данни. Изпълнете този
SELECTкоманда:SELECT * FROM customers;Трябва да видите този списък с клиенти:
+-------------+-----------------+ | 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) -
Създайте
salesмаса. Тази таблица използва колонатаcustomer_idза справка сcustomersтаблица:CREATE TABLE sales ( order_id BIGINT PRIMARY KEY AUTO_INCREMENT, customer_id BIGINT, sales_amount DECIMAL(17,2) ) ENGINE = InnoDB;Появява се този изход:
Query OK, 0 rows affected (0.03 sec) -
След това попълнете
salesтаблица с някои записи. Изпълнете долнияINSERTкоманди една по една: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');Този изход се показва след вмъкване на всеки запис:
Query OK, 1 row affected (0.01 sec) ... -
Проверете данните в
salesмаса. Изпълнете тозиSELECTкоманда:SELECT * FROM sales;Сега трябва да се покаже този списък с данни за продажбите:
+----------+-------------+--------------+ | 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)
След като настроите базата данни и свързаните таблици, вече можете да внедрите различните подзаявки в MySQL.
Как да използвате корелирана подзаявка
Корелираната подзаявка е тип вложена заявка, която използва стойностите от родителска заявка. Тези видове заявки препращат към родителската заявка с колона. Вложената заявка се изпълнява веднъж за всеки ред в родителската заявка.
Примерът по-долу представя заявка, която избира всички клиенти. Вътре в заявката има свързана подзаявка, която извлича общата сума на продажбите за всеки клиент от sales таблица.
-
Изпълнете примерната заявка:
SELECT customer_id, customer_name, (SELECT SUM(sales_amount) FROM sales WHERE customer_id = customers.customer_id) as total_sales_amount FROM customers;В този пример подзаявката е
SELECT SUM(sales_amount) FROM sales WHERE customer_id = customers.customer_id, което се показва в скоби.Появява се списък с общите продажби, направени от клиенти:
+-------------+-----------------+--------------------+ | 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)Резултатът по-горе от свързаната подзаявка може да ви даде обобщен списък с поръчките на клиентите. Моля, обърнете внимание, тъй като
customer_ids3и6нямат свързани записи в таблицата за продажби, тяхнатаtotal_sales_amountеNULL. -
По-елегантен начин да представите този списък е да върнете
0вместоNULLза клиенти с нулеви продажби. За да направите това, оградете изхода, генериран от подзаявката сIFNULL(expression, 0)изявление. Изпълнете тази актуализирана команда: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;Появява се следният изход. MySQL връща 0.00 за всички редове, които иначе биха върнали
NULLстойности.+-------------+-----------------+--------------------+ | 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)Този подход помага да се гарантира, че изходът няма да навреди на по-нататъшни изчисления на записите.
Как да използвате корелирана подзаявка в оператор за сравнение
Подзаявките са полезни за преместване на бизнес логиката на ниво заявка за база данни. Следните бизнес случаи на използване включват корелирани подзаявки, поставени в клаузата WHERE на родителска заявка:
-
Помислете за сценарий, при който бихте искали да получите списък с всички клиенти, регистрирани в базата данни, които нямат свързани продажби. Можете да използвате подзаявка заедно с оператора за сравнение на MySQL
NOT INи извлечете тези клиенти:SELECT customer_id, customer_name FROM customers WHERE customer_id NOT IN (SELECT customer_id FROM sales);В този пример подзаявката е
SELECT customer_id FROM sales, което се появява в скоби. Командата SQL по-горе извежда списък с двама клиенти, които не са открити в таблицата за продажби:+-------------+---------------+ | customer_id | customer_name | +-------------+---------------+ | 3 | MARY DOE | | 6 | FRANK BRIAN | +-------------+---------------+ 2 rows in set (0.00 sec)В производствена среда можете да използвате този вид набор от записи, за да вземате по-добри бизнес решения. Например, можете да създадете скрипт, използвайки друг език като PHP или Python, за да изпратите имейл до тези клиенти и да попитате дали имат проблем с поставянето на поръчка.
-
Друг случай на употреба е почистването на данни. Например, можете да използвате подзаявка, за да изтриете клиенти, които никога не са направили поръчка:
DELETE FROM customers WHERE customer_id NOT IN (SELECT customer_id FROM sales);Командата SQL по-горе изтрива двата клиента и извежда следното:
Query OK, 2 rows affected (0.01 sec)Ако изпълните команда за изброяване на всички клиенти отново, тези клиенти вече не трябва да се показват в таблицата:
SELECT * FROM customers;Изходът по-долу потвърждава, че клиентите без свързани поръчки са били изтрити:
+-------------+-----------------+ | customer_id | customer_name | +-------------+-----------------+ | 1 | JOHN PAUL | | 2 | PETER DOE | | 4 | CHRISTINE JAMES | | 5 | MARK WELL | +-------------+-----------------+ 4 rows in set (0.00 sec)
Как да използвате подзаявка като производна таблица
Когато се използват подзаявки в FROM клауза на родителска заявка, те се наричат производни таблици . Те са много важни при внедряване на сложни заявки, които иначе биха изисквали MySQL VIEW , JOIN или UNION клауза. В заявката, която я е създала, съществува извлечена таблица и не е запазена за постоянно в базата данни.
Когато подзаявките се използват като производни таблици, те изолират различните части на SQL израза. С други думи, подзаявката предоставя опростен израз на таблица, която може да се използва в обхвата на родителската заявка.
Забележка Не забравяйте, че всяка извлечена таблица трябва да има псевдоним.
Изпълнете командата по-долу, за да създадете подзаявка на извлечена таблица, която е с псевдоним като 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;
ЗабележкаВ тази команда подзаявката се появява в скоби като:
SELECT customer_id, count(order_id) as total_orders FROM sales group by customer_id
Горната команда прави заявка в таблицата за продажби, за да определи клиенти с повече от 1 поръчка. Когато стартирате заявката, се появява този изход:
+-------------+
| customer_id |
+-------------+
| 1 |
| 2 |
| 5 |
| 4 |
+-------------+
4 rows in set (0.00 sec)
Горният списък показва четири customer_id които имат повече от една поръчка. Като примерен случай на бизнес употреба можете да използвате такава заявка в скрипт, който награждава клиентите с бонус при следващата им покупка.
Повече информация
Може да пожелаете да се консултирате със следните ресурси за допълнителна информация по тази тема. Въпреки че те са предоставени с надеждата, че ще бъдат полезни, моля, имайте предвид, че не можем да гарантираме за точността или навременността на външно хостваните материали.
- Подзаявки за MySQL