Дэд асуулга (Subquery)
Нэг SELECT асуулгын үр дүнг нөгөө асуулгын оролт болгон ашиглаж болно — үүнийг subquery буюу дэд асуулга гэнэ. Энэ арга нь нарийн төвөгтэй асуултуудад маш тод, ойлгомжтой хариулт өгдөг. Эхэндээ хэцүү санагдаж болох ч хэдэн жишээ харвал аяндаа ойлгогдоно.
Subquery гэж юу вэ?
Subquery бол гадаад асуулгын дотор хаалтанд бичигдсэн хоёр дахь SELECT асуулга юм. PostgreSQL эхлээд дотоод (дэд) асуулгыг гүйцэтгэж, үр дүнг нь гадаад асуулгад дамжуулдаг.
Жишээ болгон хоёр хүснэгт ашиглая:
CREATE TABLE products (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
price NUMERIC NOT NULL,
category TEXT NOT NULL
);
INSERT INTO products (name, price, category) VALUES
('Утас', 850000, 'электроник'),
('Чихэвч', 45000, 'электроник'),
('Гар чийдэн', 12000, 'электроник'),
('Цамц', 35000, 'хувцас'),
('Өмд', 55000, 'хувцас'),
('Гутал', 120000, 'хувцас');
WHERE дотор subquery
Хамгийн нийтлэг хэрэглээ — нэгтгэх функцийн үр дүнтэй харьцуулах:
-- Дундаж үнээс дээш бараануудыг олох
SELECT name, price
FROM products
WHERE price > (SELECT AVG(price) FROM products);
Дотоод асуулга AVG(price) буцаана — жишээлбэл 186166. Дараа нь гадаад асуулга 186166-аас дээш үнэтэй бараануудыг шүүнэ.
-- Хамгийн үнэтэй барааг олох (MAX ашиглахгүйгээр)
SELECT name, price
FROM products
WHERE price = (SELECT MAX(price) FROM products);
-- Үр дүн: Утас — 850000
FROM дотор subquery
Subquery-г хүснэгт шиг FROM-д ашиглаж болно. Ийм subquery-г derived table гэж нэрлэдэг.
-- Категори тус бүрийн дундаж үнийг тооцоод,
-- зөвхөн 50000-аас дээш дунджийг харуулах
SELECT category, дундаж_үнэ
FROM (
SELECT category, ROUND(AVG(price), 0) AS дундаж_үнэ
FROM products
GROUP BY category
) AS category_stats
WHERE дундаж_үнэ > 50000;
FROM-д ашиглаж байгаа subquery-д заавал AS нэр өгөх ёстой (category_stats).
SELECT дотор subquery (scalar subquery)
SELECT дотор нэг утга буцаадаг subquery ашиглаж болно:
-- Бүх бараануудын үнийг нийт дунджтай харьцуулж харуулах
SELECT
name,
price,
(SELECT ROUND(AVG(price), 0) FROM products) AS нийт_дундаж,
price - (SELECT ROUND(AVG(price), 0) FROM products) AS зөрүү
FROM products
ORDER BY зөрүү DESC;
EXISTS — бичлэг байгаа эсэхийг шалгах
EXISTS нь subquery хамт ашиглагдаж, тухайн нөхцөлийг хангасан бичлэг байгаа эсэхийг шалгана:
CREATE TABLE orders (
id SERIAL PRIMARY KEY,
product_id INT REFERENCES products(id),
quantity INT NOT NULL
);
INSERT INTO orders (product_id, quantity) VALUES (1, 2), (3, 5);
-- Захиалга байгаа бараануудыг харуулах
SELECT name, price
FROM products p
WHERE EXISTS (
SELECT 1 FROM orders o WHERE o.product_id = p.id
);
SELECT 1 гэдэг нь ямар нэгэн утга буцаах биш, зүгээр л "бичлэг байна" гэсэн утгаар ашиглагддаг хурдан арга юм.
Дараагийн хичээлд:
Subquery-тэй төстэй, гэхдээ илүү уншихад хялбар, давтан ашиглагдах CTE (WITH) синтакс-ыг сурна.