Subquery — boshqa SQL statement ichida joylashgan ichki query. U scalar qiymat, row, columnlar to‘plami yoki derived table natijasini yaratishi mumkin.
Subquery SELECT, FROM, WHERE, HAVING, INSERT, UPDATE va DELETE ichida ishlatiladi.
Scalar subquery
Bitta row va bitta column qaytarishi kutiladi.
SELECT
name,
(SELECT MAX(created_at) FROM orders) AS last_order_time
FROM users;
Agar scalar subquery bir nechta row qaytarsa database xato beradi.
Hech row bo‘lmasa natija NULL bo‘lishi mumkin.
WHERE ichidagi subquery
Filter qiymati ichki query’dan olinadi.
SELECT *
FROM orders
WHERE user_id IN (
SELECT id
FROM users
WHERE active = true
);
Optimizer buni semi join yoki boshqa planga aylantirishi mumkin.
IN
Subquery qaytargan qiymatlar to‘plamiga membership tekshiradi.
Kichik statik ro‘yxat va subquery uchun qulay.
NOT IN ichki natijada NULL bo‘lsa SQL uch qiymatli mantiqi sabab kutilmaganda hech row qaytarmasligi mumkin.
Anti join uchun NOT EXISTS ko‘pincha xavfsizroq.
EXISTS
Ichki query kamida bitta row qaytarsa true.
SELECT *
FROM users u
WHERE EXISTS (
SELECT 1
FROM orders o
WHERE o.user_id = u.id
);
Ichki projectiondagi 1 qiymatining o‘zi muhim emas.
Database birinchi mos row topilgach qidirishni to‘xtatishi mumkin.
NOT EXISTS
Mos child row bo‘lmagan parentlarni topadi.
SELECT *
FROM users u
WHERE NOT EXISTS (
SELECT 1
FROM orders o
WHERE o.user_id = u.id
);
Bu anti join semantikasi.
Null qiymatlar bilan NOT INga qaraganda aniqroq.
Correlated subquery
Ichki query tashqi query rowiga murojaat qiladi.
SELECT *
FROM products p
WHERE price > (
SELECT AVG(p2.price)
FROM products p2
WHERE p2.category_id = p.category_id
);
Har product o‘z category o‘rtachasi bilan solishtiriladi.
Optimizer uni join va aggregationga qayta yozishi mumkin.
Uncorrelated subquery
Ichki query tashqi rowga bog‘liq emas.
U bir marta hisoblanishi yoki optimizer tomonidan alohida plan qilinishi mumkin.
Misol, barcha orderlarni global average bilan solishtirish.
Derived table
FROM ichidagi subquery vaqtinchalik tablega o‘xshash natija beradi.
SELECT x.category_id, x.total
FROM (
SELECT category_id, SUM(amount) AS total
FROM sales
GROUP BY category_id
) AS x;
Derived table aliasga ega bo‘lishi kerak bo‘lishi mumkin.
Lateral subquery
Lateral subquery FROM ichida oldingi table rowlariga murojaat qiladi.
Bu har parent uchun top N child, computed set yoki parameterized function chaqirish uchun qulay.
Masalan, har userning eng so‘nggi uchta orderi.
Aniq syntax database’ga bog‘liq.
SELECT list subquery
Har outer row uchun bitta qiymat olish mumkin.
SELECT
u.id,
(
SELECT COUNT(*)
FROM orders o
WHERE o.user_id = u.id
) AS order_count
FROM users u;
Katta datasetda aggregation join yoki precomputed count samaraliroq bo‘lishi mumkin.
UPDATE ichidagi subquery
Update qiymati yoki filter ichki query’dan olinadi.
UPDATE products
SET category_name = (
SELECT name
FROM categories
WHERE categories.id = products.category_id
);
Scalar natija va null holati tekshiriladi.
Ko‘p database UPDATE ... FROMga o‘xshash join syntaxini ham beradi.
DELETE ichidagi subquery
Bog‘liq bo‘lmagan yoki eskirgan rowlarni ichki query orqali topish mumkin.
DELETE FROM sessions
WHERE user_id IN (
SELECT id FROM users WHERE deleted_at IS NOT NULL
);
Katta delete batch, lock va WAL hajmi bo‘yicha boshqariladi.
Subquery va join
Ko‘p subquery join bilan qayta yozilishi mumkin.
Lekin semantika bir xil bo‘lishi shart emas.
Masalan, child mavjudligini tekshirish uchun join duplicate parent rowlar yaratishi mumkin.
EXISTS kerakli ma’noni aniq ifodalaydi.
Subquery flattening
Optimizer ichki queryni outer query bilan birlashtirishi mumkin.
Bu predicate pushdown va join reorder imkonini beradi.
LIMIT, aggregation, window function yoki volatile expression optimization barrier bo‘lishi mumkin.
Materialization
Database subquery natijasini vaqtinchalik saqlab, keyin qayta ishlatishi mumkin.
Materialization:
- qayta hisoblashni kamaytiradi;
- memory yoki temp disk ishlatadi;
- tashqi filter pushdownini cheklashi mumkin.
Execution plan haqiqiy tanlovni ko‘rsatadi.
Performance
Correlated subquery har outer row uchun ishlayotgandek ko‘rinishi mumkin.
Optimizer decorrelation qilmasa N marta execution yuz beradi.
Index, row soni, aggregation va cache performance’ga ta’sir qiladi.
EXPLAIN orqali loop soni tekshiriladi.
Readability
Juda chuqur nested subquery queryni tushunishni qiyinlashtiradi.
Nomlangan CTE:
- bosqichlarni ajratish;
- qayta ishlatish;
- debugging;
- business ma’noli alias
uchun ishlatilishi mumkin.
Biroq CTE performance semantikasi database versiyasiga bog‘liq.
Quantified comparison
Subquery natijasi ANY, SOME yoki ALLga o‘xshash operatorlar bilan solishtirilishi mumkin.
Masalan, qiymat barcha qaytgan qiymatlardan katta yoki kamida bittasiga tengligini tekshirish.
Bo‘sh natija va NULL semantikasi alohida hisobga olinadi.
Scalar cache
Uncorrelated scalar subquery optimizer tomonidan bir marta hisoblanishi mumkin.
Volatile function yoki tashqi dependency mavjud bo‘lsa qayta execution semantikasi o‘zgaradi.
Execution plan subquery necha marta ishlaganini ko‘rsatadi.
Bog‘liq tushunchalar
Nested query, Scalar subquery, Correlated subquery, EXISTS, IN, Derived table, Lateral join, Query optimizer, CTE, Semi join