Subquery
Subquery (дэд query) нь өөр SQL мэдэгдлийн дотор байрлах query юм. Нарийн шүүлт, харьцуулалт хийхэд хүчтэй хэрэгсэл.
Суурь жишээ
CREATE TABLE products (
id INT PRIMARY KEY AUTO_INCREMENT,
name TEXT NOT NULL,
price DECIMAL(10,2),
stock INT
);
CREATE TABLE orders (
id INT PRIMARY KEY AUTO_INCREMENT,
product_id INT REFERENCES products(id),
customer TEXT,
quantity INT
);
INSERT INTO products (name, price, stock) VALUES
('Ном', 15000, 50),
('Дэвтэр', 3500, 200),
('Үзэг', 1200, 500),
('Тоглоом', 45000, 10);
INSERT INTO orders (product_id, customer, quantity) VALUES
(1, 'Болд', 2),
(2, 'Оюун', 5),
(1, 'Дорж', 1),
(3, 'Болд', 10),
(1, 'Оюун', 3);
WHERE дахь subquery
-- Дундаж үнээс өндөр бараанууд
SELECT name, price
FROM products
WHERE price > (SELECT AVG(price) FROM products);
name | price
---------|------
Ном | 15000
Тоглоом | 45000
Дотоод query (SELECT AVG(price) FROM products) эхлээд ажиллаж нэг тоо буцаана, дараа нь гадна query тэр тоотой харьцуулна.
-- Хамгийн их захиалга авсан барааны мэдээлэл
SELECT name, price
FROM products
WHERE id = (
SELECT product_id
FROM orders
GROUP BY product_id
ORDER BY SUM(quantity) DESC
LIMIT 1
);
IN оператор — олон утгатай харьцуулах
-- Захиалга авсан бараануудын жагсаалт
SELECT name, price
FROM products
WHERE id IN (SELECT DISTINCT product_id FROM orders);
-- Захиалга аваагүй бараануудын жагсаалт
SELECT name, price
FROM products
WHERE id NOT IN (SELECT DISTINCT product_id FROM orders);
IN нь subquery олон мөр буцаах үед ашиглана. = (subquery) зөвхөн нэг утга буцаана гэж найдвартай мэдэх үед.
EXISTS оператор — байгаа эсэхийг шалгах
-- Дор хаяж нэг захиалга авсан бараанууд
SELECT name
FROM products p
WHERE EXISTS (
SELECT 1
FROM orders o
WHERE o.product_id = p.id
);
EXISTS нь subquery хэдэн ч мөр буцаасан хамаагүй — байгаа эсэхийг л шалгана. SELECT 1 ашигладаг учир нь ямар утга буцаахаас хамаагүй, зөвхөн мөр байгаа эсэх л чухал.
ANY ба ALL
-- Аль нэг захиалгын тоо хэмжээнээс их нөөцтэй бараанууд
SELECT name, stock
FROM products
WHERE stock > ANY (SELECT quantity FROM orders);
-- stock > 1 байвал хангалттай (хамгийн бага утгаас их)
-- Бүх захиалгын тоо хэмжээнээс их нөөцтэй бараанууд
SELECT name, stock
FROM products
WHERE stock > ALL (SELECT quantity FROM orders);
-- stock > 10 байх ёстой (хамгийн их утгаас их)
FROM дахь subquery (derived table)
-- Хэрэглэгч бүрийн нийт зарцуулалтын дундаж
SELECT AVG(нийт) AS дундаж_зарцуулалт
FROM (
SELECT customer, SUM(p.price * o.quantity) AS нийт
FROM orders o
JOIN products p ON o.product_id = p.id
GROUP BY customer
) AS хэрэглэгч_нийт;
FROM дахь subquery-г derived table буюу гаралтын хүснэгт гэнэ. Заавал alias өгөх шаардлагатай (AS хэрэглэгч_нийт).
Correlated subquery
Correlated subquery нь гадна query-н мөр бүрт тусад нь ажилладаг — гадна query-н утгыг дотор ашигладаг.
-- Бүх барааны дундаж үнээс өндөр үнэтэй барааг тус тусын дундажтай харьцуулах
SELECT name, price,
(SELECT AVG(price) FROM products) AS ерөнхий_дундаж
FROM products
WHERE price > (SELECT AVG(price) FROM products);
Жинхэнэ correlated subquery:
-- Хамгийн их тоогоор захиалагдсан бараа бүрийн мэдээлэл
SELECT name, price
FROM products p
WHERE (
SELECT SUM(quantity)
FROM orders o
WHERE o.product_id = p.id -- гадна query-н p.id ашиглаж байна
) > 3;
Subquery vs JOIN
Ихэнх subquery-г JOIN-аар бас бичиж болно:
-- Subquery хувилбар
SELECT name FROM products
WHERE id IN (SELECT product_id FROM orders);
-- JOIN хувилбар (ихэвчлэн хурдан)
SELECT DISTINCT p.name
FROM products p
JOIN orders o ON p.id = o.product_id;
Том хүснэгтэд JOIN нь subquery-аас хурдан байдаг. Гэхдээ subquery нь заримдаа уншихад илүү ойлгомжтой.
Дараагийн хичээлд:
String функцүүд — текст боловсруулах CONCAT, SUBSTRING, REPLACE, LIKE зэрэг функцүүдийг үзнэ.