CodeGym /Kurslar /SQL SELF /Pəncərə funksiyalarından istifadə zamanı tipik səhvlər

Pəncərə funksiyalarından istifadə zamanı tipik səhvlər

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

İndi isə gəlin pəncərə funksiyaları ilə işləyərkən ortaya çıxa biləcək çətinliklərdən danışaq. Hər zamanki kimi, proqramlaşdırmada (və həyatda) başqalarının səhvlərindən öyrənmək daha yaxşıdır. İndi həm yeni başlayanların, həm də bəzən təcrübəli developerlərin yol verdiyi tipik səhvləri müzakirə edəcəyik və onlardan necə qaçmaq lazım olduğunu öyrənəcəyik.

Səhv №1: PARTITION BY-dan düzgün istifadə etməmək

Ən çox rast gəlinən səhvlərdən biri — PARTITION BY parametrini unutmaq və ya səhv yazmaqdır, xüsusilə də datanı qruplara bölmək istəyəndə. Onsuz PostgreSQL bütün sətirləri bir böyük qrup kimi götürəcək və nəticələr gözlədiyiniz kimi olmayacaq.

Tutaq ki, bizdə sales adlı bir cədvəl var və burada satışlar haqqında məlumat saxlanılır:

id region month total
1 North 2023-01 1000
2 South 2023-01 800
3 North 2023-02 1200
4 South 2023-02 900

Hər region üçün aylara görə yığılan cəmi (SUM()) tapmaq istəyirsən. Belə bir sorğu yaza bilərsən:

SELECT
    region,
    month,
    SUM(total) OVER (ORDER BY month) AS running_total
FROM 
    sales;

Nəticə:

region month running_total
North 2023-01 1000
South 2023-01 1800
North 2023-02 3000
South 2023-02 3900

İlk baxışda hər şey qaydasındadır. Amma nəticə gözlədiyimiz kimi deyil, çünki yığılan cəm regionlara görə yox, bütün sətirlər üçün hesablanır. Problem ondadır ki, PARTITION BY region əlavə etməyi unutmuşuq.

Düzgün kod:

SELECT 
    region,
    month,
    SUM(total) OVER (PARTITION BY region ORDER BY month) AS running_total
FROM 
    sales;

Nəticə:

region month running_total
North 2023-01 1000
North 2023-02 2200
South 2023-01 800
South 2023-02 1700

İndi hər şey düz işləyir: datalar regionlara görə qruplaşdırılır və yığılan cəm hər region üçün ayrıca hesablanır.

Səhv №2: ORDER BY-da düzgün sıralama verməmək

ORDER BY OVER() içində pəncərə daxilində sətirlərin sırasını təyin edir. Əgər sıralama səhvdirsə, nəticələr də gözlənilməz olacaq.

Satışların yığılan cəmini ayların azalan sırasına görə tapmaq istəyirsən. Belə bir sorğu yaza bilərsən:

SELECT
    month,
    total,
    SUM(total) OVER (ORDER BY month DESC) AS running_total
FROM 
    sales;

Nəticə:

month total running_total
2023-02 1200 1200
2023-02 900 2100
2023-01 1000 3100
2023-01 800 3900

İlk baxışda düz görünür, amma diqqət et: sətirlər aylar üzrə qruplaşıb, amma cəmlər düzgün hesablanmayıb, çünki sıralama azalan verilib. Ona görə nəticələr qarışıq çıxır.

Düzəliş: sorğunu düzgün ORDER BY ilə yaz:

SELECT
    month,
    total,
    SUM(total) OVER (ORDER BY month ASC) AS running_total
FROM 
    sales;

Səhv №3: Pəncərə funksiyalarını indeks olmadan istifadə etmək

Pəncərə funksiyaları çox vaxt böyük həcmli datalarla işləyir və əsas sütunlarda indeks yoxdursa, performans bərbad ola bilər.

Nümunə: bizdə milyonlarla sətri olan large_sales cədvəli var və satışların rank-larını hesablamaq istəyirik:

SELECT
    id,
    total,
    RANK() OVER (ORDER BY total DESC) AS rank
FROM 
    large_sales;

Az datada sorğu tez işləyəcək, amma böyük həcmdə bu, sonsuz çəkə bilər.

Düzəliş: ORDER BY-da istifadə olunan sütunda indeks yarat:

CREATE INDEX idx_total ON large_sales(total DESC);

İndi sorğu xeyli tez işləyəcək.

Səhv №4: ROWS və ya RANGE ilə pəncərənin necə işlədiyini başa düşməmək

ROWSRANGE istifadə edəndə, onların pəncərəni necə hesablamağını başa düşmək vacibdir. Bu açar sözləri səhv başa düşsən, nəticələr gözlənilməz olacaq.

Nümunə: indiki ay və əvvəlki iki ay üçün satışların hərəkətli ortasını hesablamaq istəyirsən:

SELECT
    month,
    AVG(total) OVER (ORDER BY month ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS moving_avg
FROM 
    sales;

Əgər ROWS əvəzinə RANGE yazsan:

SELECT
    month,
    AVG(total) OVER (ORDER BY month RANGE BETWEEN 2 PRECEDING AND CURRENT ROW) AS moving_avg
FROM 
    sales;

Nəticə fərqli olacaq, çünki RANGE konkret sətir sayına yox, dəyər aralığına baxır.

Səhv №5: Pəncərə funksiyalarından həddindən artıq istifadə

Bir sorğuda bir neçə pəncərə funksiyası istifadə etmək hesablamaların təkrarlanmasına və performansın düşməsinə səbəb ola bilər.

Nümunə:

SELECT 
    id,
    total,
    SUM(total) OVER (PARTITION BY region) AS region_total,
    SUM(total) OVER (PARTITION BY region) / COUNT(total) OVER (PARTITION BY region) AS region_avg
FROM 
    sales;

Burada SUM(total)COUNT(total) hər sətir üçün bir neçə dəfə hesablanır.

Düzəliş: sorğunu alt-sorğular və ya CTE ilə qısalt:

WITH cte_region_totals AS (
    SELECT 
        region,
        SUM(total) AS region_total,
        COUNT(total) AS region_count
    FROM 
        sales
    GROUP BY 
        region
)
SELECT 
    s.id,
    s.total,
    t.region_total,
    t.region_total / t.region_count AS region_avg
FROM 
    sales s
JOIN 
    cte_region_totals t ON s.region = t.region;

Səhvlərdən qaçmaq üçün məsləhətlər

PARTITION BYORDER BY-ı yoxla: həmişə pəncərənin düzgün verildiyinə əmin ol.

Dataları indekslə: xüsusilə sıralama (ORDER BY) və ya filtrasiya istifadə edirsənsə.

Çoxlu hesablamalar üçün CTE istifadə et: bu, təkrarlanan addımları azaltmağa kömək edəcək.

İcra planına bax: sorğunu PostgreSQL necə işlədiyini başa düşmək üçün EXPLAINEXPLAIN ANALYZE istifadə et.

Real datada test et: nəticələrin gözləntilərinə uyğun olduğuna və tapşırığın düzgün həll olunduğuna əmin ol.

2
Tapşırıq
SQL SELF, səviyyə, dərs
Bağlanıb
ORDER BY-dan pəncərə funksiyalarında istifadə
ORDER BY-dan pəncərə funksiyalarında istifadə
1
Sorğu/viktorina
, səviyyə, dərs
Əlçatan deyil
Oken çərçivəsinin sazlanması
Oken çərçivəsinin sazlanması
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION