CodeGym /Kurslar /SQL SELF /Alt-sorgularla işləyərkən tipik səhvlər

Alt-sorgularla işləyərkən tipik səhvlər

SQL SELF
Səviyyə , Dərs
Mövcuddur

Alt-sorgularla işləmək elə bil soyunma şahmatı oynamaq kimidir: əvvəlcə hər şey asan görünür, ta ki səhv gediş edəndə. Bəs səhvlər haradan çıxır? Sintaksisin tam başa düşülməməsindən, SQL məntiqinin özəlliklərini nəzərə almamağından və ya sadəcə diqqətsizlikdən. Bu dərsdə ən çox rast gəlinən səhvlərdən və onlardan necə qaçmaqdan danışacağıq.

Sintaksis səhvləri

Alt-sorgularla işləyərkən sintaksisə diqqət lazımdır. Vergül, mötərizə və ya alias-un (təxəllüs) unudulması bütün sorğunu çökdürə bilər. Gəlin bir neçə tipik problemi nəzərdən keçirək.

Unudulmuş mötərizələr

Mötərizələr alt-sorgularda əsas rol oynayır. Alt-sorgu həmişə dəyirmi mötərizəyə alınmalıdır, bir cüt belə çatışmasa sintaksis səhvi çıxacaq.

Səhv nümunəsi:

SELECT student_name
FROM students
WHERE student_id IN SELECT student_id FROM enrollments);

Səhv:

ERROR:  syntax error at or near "SELECT"

Düzəliş:

SELECT student_name
FROM students
WHERE student_id IN (SELECT student_id FROM enrollments);

Şərh: IN içindəki sorğu həmişə mötərizədə olmalıdır ki, SQL başa düşsün ki, sən alt-sorgu işlətmək istəyirsən.

Alias-un olmaması

Əgər FROM hissəsində alt-sorgu istifadə edirsənsə, ona alias verməyi unutma. Onsuz PostgreSQL çaşacaq.

Səhv nümunəsi:

SELECT student_name, avg_score
FROM (SELECT student_id, AVG(score) AS avg_score FROM grades GROUP BY student_id)
WHERE avg_score > 80;

Səhv:

ERROR:  subquery in FROM must have an alias

Düzəliş:

SELECT student_name, avg_score
FROM (SELECT student_id, AVG(score) AS avg_score FROM grades GROUP BY student_id) AS subquery
WHERE avg_score > 80;

Şərh: PostgreSQL tələb edir ki, hər müvəqqəti cədvəl (FROM-da alt-sorgunun nəticəsi) ad alsın.

Performans problemləri

Alt-sorgular, xüsusilə pis optimallaşdırılmışlar, bazanı yavaş işləyən bir mexanizmə çevirə bilər. Performans adətən artıq hesablamalar və ya indekslərin olmaması səbəbindən düşür.

Artıq hesablamalar

SELECT hissəsindəki alt-sorgular hər nəticə sətri üçün ayrıca hesablanır, bu da vaxt itkisinə səbəb olur.

Nümunə:

SELECT student_name,
       (SELECT COUNT(*) FROM enrollments WHERE enrollments.student_id = students.student_id) AS course_count
FROM students;

Əgər students cədvəlində on minlərlə sətir varsa, bu alt-sorgu hər sətr üçün yenidən işləyəcək.

Optimallaşdırma:

WITH course_counts AS (
    SELECT student_id, COUNT(*) AS course_count
    FROM enrollments
    GROUP BY student_id
)
SELECT s.student_name, c.course_count
FROM students s
LEFT JOIN course_counts c ON s.student_id = c.student_id;

CTE (Common Table Expression) və ya join-lar hər sətr üçün təkrar hesablamağa ehtiyac qoymur. Bu yanaşmaya bir neçə səviyyə sonra baxacağıq :P

İndekslərin olmaması

Əgər WHERE hissəsində mürəkkəb alt-sorgular istifadə edirsənsə, lazım olan sütunların indeksli olduğuna əmin ol.

Nümunə:

SELECT student_name
FROM students
WHERE student_id IN (SELECT student_id FROM enrollments WHERE course_id = 10);

Əgər enrollments cədvəlində student_id sütununda indeks yoxdursa, alt-sorgu bütün cədvəli tam skan edəcək.

Optimallaşdırma: İndeks yaradın:

CREATE INDEX idx_enrollments_course_id ON enrollments (course_id);

İndekslər haqqında tez-tez eşidirsən, yəqin artıq maraqlanırsan ki, bu nədir. Amma bir az səbirli ol, bir neçə səviyyə sonra baxacağıq. İndekslər vacibdir, amma onlar əsasən sorğunun kodunu dəyişmədən sürətləndirməyə kömək edir. Pis sorğunu yaxşı etmirlər, sadəcə production-da sorğuları sürətləndirirlər. Xüsusilə milyonlarla sətri olan cədvəllərdə.

Məntiq səhvləri

Alt-sorgularda məntiq səhvləri sintaksis səhvləri qədər tez-tez olur. Problemlər NULL-un işləmə qaydasını, filtr və ya aqreqat funksiyaları düzgün başa düşməməkdən qaynaqlana bilər.

NULL-un səhv istifadəsi

NULL — hər yeni başlayan üçün tələdir. IN və ya NOT IN ilə alt-sorgularda NULL olması nəticəyə təsir edə bilər.

Səhv nümunəsi:

SELECT student_name
FROM students
WHERE student_id NOT IN (SELECT student_id FROM enrollments);

Əgər enrollments cədvəlində student_id = NULL olan sətir varsa, sorğu heç nə qaytarmayacaq. Bu ona görədir ki, NOT IN şərti NULL IS NOT IN kimi işləyir.

Düzəliş:

SELECT student_name
FROM students
WHERE student_id NOT IN (SELECT student_id FROM enrollments WHERE student_id IS NOT NULL);

Əgər NOT IN istifadə edirsənsə, həmişə NULL-u filtrlə.

Filtr şərtlərində səhvlər

Çox vaxt alt-sorgu mürəkkəb filtr üçün istifadə olunur, amma şərtlərdə səhv nəticənin gözləniləndən tam fərqli olmasına səbəb ola bilər.

Səhv nümunəsi:

SELECT student_name
FROM students
WHERE (SELECT AVG(score) FROM grades WHERE grades.student_id = students.student_id) > 80;

Əgər hansısa tələbənin heç bir qiyməti yoxdursa, alt-sorgu NULL qaytaracaq və tələbə nəticəyə düşməyəcək.

Düzəliş:

SELECT student_name
FROM students
WHERE COALESCE((SELECT AVG(score) FROM grades WHERE grades.student_id = students.student_id), 0) > 80;

COALESCE istifadə et ki, NULL-u default dəyərlə əvəzləyəsən.

Səhvlərin qarşısını almaq üçün tövsiyələr

Alt-sorgularla işləyərkən tipik səhvlərdən qaçmaq üçün bu qaydalara əməl et:

Mötərizə və alias-lardan düzgün istifadə. Nəsə işləmirsə, bütün mötərizələrin bağlanıb-bağlanmadığını və alt-sorgularda alias verilib-verilmədiyini yoxla.

Sorğuların optimallaşdırılması. Alt-sorgu yerinə JOIN, WITH və ya indekslərdən istifadə etməyə çalış.

NULL-u nəzərə al. Alt-sorgularda NULL ola biləcəyini həmişə düşün və IS NOT NULL, COALESCE və ya oxşar konstruksiyalardan istifadə et.

Test et. Hər alt-sorgunu ayrıca yoxla ki, istədiyin nəticəni qaytardığına əmin olasan.

Oxunaqlılıq. Kodunu oxunaqlı etmək üçün boşluq və alias-lardan istifadə et. Unutma: bir ay sonra özün belə nə yazdığını xatırlamaya bilərsən.

1
Sorğu/viktorina
, səviyyə, dərs
Əlçatan deyil
Subquery-lərin istifadəsi
Subquery-lərin istifadəsi
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION