FROM içində subquery-lərdən istifadə
Gəlin bir az da dərinliyə gedək: FROM içində subquery-lərdən necə istifadə etməyi baxaq. Bu SQL developer-ların ən çox istifadə etdiyi yanaşmalardan biridir, çünki beləliklə güclü müvəqqəti cədvəlləri birbaşa "yerində" yarada və onları sanki bazada mövcud cədvəllər kimi istifadə edə bilərsən.
Təsəvvür elə ki, bir hesabat hazırlayırsan və orada hesablama, qruplaşdırma və ya filtrasiya lazımdır, amma əlavə müvəqqəti cədvəl yaratmaq istəmirsən. Nə etməli? Bax, burada FROM içində subquery-lər köməyə gəlir. Onlar sənə imkan verir:
- Müvəqqəti olaraq datanı birləşdirmək və ya əsas sorğudan əvvəl aggregate etmək.
- "Uçan" strukturlu dataset-lər yaratmaq.
- Əməliyyatların sayını azaltmaq, yəni bazadan minimal aralıq data saxlanmasını tələb etmək.
FROM içində subquery-lər mini-cədvəllər kimi işləyir və əsas sorğuda istifadə oluna bilər. Bu, sanki modul konstruksiya yığmaq kimidir: tez, çevik və əlavə overhead olmadan :)
FROM içində subquery-lərin əsasları
FROM içində subquery-lərdə biz subquery yazıb müvəqqəti cədvəl (və ya subtable) yaradırıq və bu, ümumi sorğunun bir hissəsinə çevrilir. Bunun üçün 3 əsas addım var:
- Subquery-ni FROM hissəsində mötərizədə yazırsan.
- Subquery-yə alias (təxəllüs) verirsən.
- Bu alias-ı sanki tam cədvəl kimi istifadə edirsən.
Sintaksis
SELECT sütunlar
FROM (
SELECT sütunlar
FROM cədvəl
WHERE şərt
) AS təxəllüs
WHERE xarici_şərt;
Qorxulu səsləndi? Gəlin nümunələrə keçək.
Nümunə: Tələbələr və orta bal
Tutaq ki, bizdə iki cədvəl var:
students (tələbələr haqqında məlumat — ad və ID):
| student_id | student_name |
|---|---|
| 1 | Alex |
| 2 | Anna |
| 3 | Dan |
grades (tələbələrin qiymətləri):
| grade_id | student_id | grade |
|---|---|---|
| 1 | 1 | 80 |
| 2 | 1 | 85 |
| 3 | 2 | 90 |
| 4 | 3 | 70 |
| 5 | 3 | 75 |
İndi tapşırıq: tələbələrin siyahısını və onların orta balını almaq.
Əvvəlcə hər tələbənin orta balını hesablayan sadə subquery ilə başlaya bilərik, sonra onu əsas sorğuda istifadə edirik.
SELECT s.student_name, g.avg_grade
FROM (
SELECT student_id, AVG(grade) AS avg_grade
FROM grades
GROUP BY student_id
) AS g
JOIN students AS s ON s.student_id = g.student_id;
Nəticə:
| student_name | avg_grade |
|---|---|
| Alex | 82.5 |
| Anna | 90.0 |
| Dan | 72.5 |
"Uçan" müvəqqəti cədvəllər
FROM içində subquery-lər xüsusilə faydalıdır, əgər bir neçə səviyyədə data işləmək lazımdırsa. Məsələn, təkcə orta bal yox, həm də hər tələbə üçün maksimum balı hesablamaq istəyirsənsə — hamısını bir sorğuda.
SELECT g.student_id, g.avg_grade, g.max_grade
FROM (
SELECT student_id,
AVG(grade) AS avg_grade,
MAX(grade) AS max_grade
FROM grades
GROUP BY student_id
) AS g;
Nəticə:
| student_id | avg_grade | max_grade |
|---|---|---|
| 1 | 82.5 | 85 |
| 2 | 90 | 90 |
| 3 | 72.5 | 75 |
Fikir ver, bu tam müvəqqəti cədvəl kimi işləyir və öz sütun adları var: avg_grade və max_grade.
FROM içində subquery-ləri nə vaxt istifadə etmək daha yaxşıdır?
Aggregated data üçün. Əvvəlcə hesablama (məsələn, orta, cəmlər və ya maksimumlar) aparmaq, sonra nəticəni başqa cədvəllərlə birləşdirmək istəyirsənsə.
Data filtrasiya üçün. Əsas cədvəllə birləşdirmədən əvvəl datanı filtrasiya etmək lazım olanda.
Çətin sorğuları asanlaşdırmaq üçün. Çətin tapşırıqları mərhələlərə bölmək qarışıqlığın qarşısını alır.
Nümunə: İki səviyyəli tələbə hesabatı
Tutaq ki, orta balı 80-dən yuxarı olan tələbələri tapmaq istəyirik. Əvvəlcə orta balı hesablayan subquery yazırıq, sonra onu filterdə istifadə edirik.
SELECT s.student_name, g.avg_grade
FROM students AS s
JOIN (
SELECT student_id, AVG(grade) AS avg_grade
FROM grades
GROUP BY student_id
) AS g ON s.student_id = g.student_id
WHERE g.avg_grade > 80;
Nəticə:
| student_name | avg_grade |
|---|---|
| Alex | 82.5 |
| Anna | 90.0 |
İstifadə xüsusiyyətləri və tövsiyələr
Mütləq alias. Subquery-yə həmişə alias ver (məsələn, AS g), yoxsa PostgreSQL bu "müvəqqəti cədvələ" necə müraciət edəcəyini anlamayacaq.
Optimallaşdırma. FROM içində subquery-lər bəzən table join-lardan (JOIN) daha yavaş ola bilər, xüsusilə də subquery daxilində filtrasiya edirsənsə.
İndeksləmə. Join, indeks və filter üçün istifadə olunan sahələrin optimallaşdırıldığından əmin ol — bu performansa ciddi təsir edir.
Çətin sorğu nümunəsi: kurslar və tələbə sayı
İndi isə bir az daha çətin real tapşırıq edək. Təsəvvür elə ki, belə bir cədvəlimiz var:
courses (kursların siyahısı):
| course_id | course_name |
|---|---|
| 1 | SQL Basics |
| 2 | Python Basics |
Və enrollments (tələbələrin kurslara yazılması):
| student_id | course_id |
|---|---|
| 1 | 1 |
| 1 | 2 |
| 2 | 1 |
İndi isə hər kursa neçə tələbə yazılıb onu bilmək istəyirik.
SELECT c.course_name, e.students_count
FROM courses AS c
JOIN (
SELECT course_id, COUNT(student_id) AS students_count
FROM enrollments
GROUP BY course_id
) AS e ON c.course_id = e.course_id;
Nəticə:
| course_name | students_count |
|---|---|
| SQL Basics | 2 |
| Python Basics | 1 |
Ümid edirəm leksiya xoşuna gəldi... amma növbəti daha maraqlı olacaq :)
GO TO FULL VERSION