Aggregated Data Using The Group Functions

Salam, Bloguma xoş gəlmisiniz.

Bugünkü mövzumuz ORACLE SQL-in bir digər maraqlı bölməsi olan “aggregate” funksiyalardır. Keçən yazımızda xatırlıyırsınızsa scalar bir digər adı ilə “single-row ”funksiyalardan danışmışdıq, bu dəfəki mövzumuz isə “multirow” və ya aggregate funksiyalardır. Aggregate funksiyalar çoxlu sətir məlumatını qəbul edib bizə bir nəticə qaytarır. Bu yazımda əsasən aşağıdakı funksiyalardan danışacağam.

aggregate_functions_list

Aggregate funksiyaları sql sorğularda istifadə edəcəyimiz bəlli yerlər vardır.

  • SELECT ifadəsi və ORDER BY-da
  • GROUP BY
  • HAVİNG

İndi isə ən çox istifadə olunan aggregate funksiyalardan bəhs edək.

COUNT

COUNT(e1)

e1 – istənilən verilən tipində ola bilən sütun adıdır.

Verilmiş sütunda olan bütün NOT NULL sətirlərin sayını qaytracaq bizə.

Məsələn VENDORS cədvəlinə baxaq.

vendor_table

SELECT VENDOR_NAME, STATUS, CATEGORY FROM VENDORS;

VENDOR_NAME         STATUS       CATEGORY

——————————   —————– ————–

Acme Steaks                17

Acme Poker

SELECT COUNT(VENDOR_NAME), COUNT(STATUS), COUNT(CATEGORY) FROM VENDORS;

COUNT(VENDOR_NAME)  COUNT(STATUS)  COUNT(CATEGORY)

————————————–  —————————  ———————-

2                                                  1                                0

Nəticədən də göründüyü kimi NULL olan dəyərlər COUNT-a daxil edilmədi. Ancaq COUNT vasitəsilə NULL olanlarıda nəzərə alıb sütundakı bütün sətirləri saymaq olar, bunun üçün e1 parametri yerinə asteriks(*) yazmaq kifayətdir.

SELECT COUNT(*) FROM VENDORS;

COUNT(*)

——————

2

Aggregate funksiyalar daxilində DİSTİNCT ALL operatorlarını da istifadə etmək mümkündür. Məs:

SELECT COUNT(DISTINCT LAST_NAME), COUNT(ALL LAST_NAME) FROM EMPLOYEES;

COUNT(DISTINCTLAST_NAME)  COUNT(ALLLAST_NAME)

————————————————  ———————————

5                                                       7

SUM

SUM(e1)

e1 – sadəcə ədəd tipində olan məlumat sütunudur.

SELECT SUM(SUBTOTAL) FROM ORDERS;
SELECT SUM(SUBTOTAL) FROM ORDERS WHERE ORDER_DATE = SYSDATE;

MIN, MAX

MIN(e1), MAX(e2)

e1, e2 – tarix, ədəd və hərf(char və ya string)tiplərinin hər hansı birində olan məlumat sütunudur.

Ədəd tipi: Kiçik ədədlər MIN, böyük ədədlər MAX

Tarix tipi: Əvvəlki günlər MIN, sonrakı günlər MAX

Hərf tipi: ‘A’ < ‘Z’;  ‘Z’ < ‘a’;  ‘1’<’10’; ‘2’ > ‘100’

LAST_NAME

———————-

Hoddlestein

Smith

Worthington

Lindon

West

SELECT MIN(LAST_NAME), MAX(LAST_NAME) FROM EMPLOYEES;

MIN(LAST_NAME)           MAX(LAST_NAME)

————————————  ——————–

Hoddlestein                      Worthington

AVG

AVG(e1)

e1 – ədəd tipində olan məlumat sütunudur.

Verilmiş sütundakı ədədlərin ortalamasını hesablayır. NULL dəyərə sahib olanları nəzərə almır.

SELECT PAY_HISTORY_ID,SALARY FROM PAY_HISTORY;

PAY_HISTORY_ID  SALARY

————————–   ———————-

1                                  73922

2                                  47000

3                                  58000

4                                 37450

5                                 91379

6                                 45500

SELECT AVG(SALARY) FROM PAY_HISTORY;

AVG(SALARY)

———————-

58875.1666666666666666666666666666666667

Son nəticəni daha anlaşıqlı edək

SELECT TO_CHAR(ROUND(AVG(SALARY),2),'$999,999.99') FROM PAY_HISTORY;

TO_CHAR(ROUND(AVG(SALARY),2),’$999,999.99′)

——————————————-

$58,875.17

MEDIAN

MEDIAN(e1)

e1 – tarix və ya ədəd tipində olan məlumat sütunudur. NULL dəyərləri nəzərə almır.

Verilmis sütunu ASC(kiçikdən böyüyə doğru) formada sıralayır və ortadakı dəyəri bizə qaytarır bu qayda yalnız verilənlərin sayı tək olanda olur, cüt olduğu zaman isə ortada olan dəyərlərin ortalamasını bizə qaytarır.
CREATE TABLE TEST_MEDIAN(A NUMBER(3));

INSERT INTO TEST_MEDIAN VALUES (1);

INSERT INTO TEST_MEDIAN VALUES (10);

INSERT INTO TEST_MEDIAN VALUES (3);

SELECT MEDIAN(A) FROM TEST_MEDIAN;

MEDIAN(A)

—————–

3

Daha sonra 4 ədədini əlavə etdikdə isə nəticə belə olur.

INSERT INTO TEST_MEDIAN VALUES (4);

SELECT MEDIAN(A) FROM TEST_MEDIAN;

MEDIAN(A)

—————–

3.5

RANK

RANK(c1) WITHIN GROUP (ORDER BY e1)

c1, e1 – hərf və ədəd tiplərindən hər hansı biridirlər. Bir birlərinə ekvialent tip olmalıdırlar.

Sıralanmış(istər ASC istər DESC) e1 sütun dəyərləri içərisində c1 neçənci yerdə yerləşirsə bizə o qiyməti qaytarır. Bir nüansa diqqət etmək lazımdır əgər eyni ədəd və ya hərf düzülüşü olarsa(n eyni ədəd varsa) hər biri eyni rank qiymətini alacaq ancaq onlardan sonra gələcək dəyər n+1 rank dəyərini alacaq.

Məs:

CREATE TABLE RANK_TEST(VAL NUMBER);

INSERT INTO RANK_TEST VALUES(1);

INSERT INTO RANK_TEST VALUES(1);

INSERT INTO RANK_TEST VALUES(1);

INSERT INTO RANK_TEST VALUES(2);

SELECT RANK(1) WITHIN GROUP(ORDER BY VAL), RANK(2) WITHIN GROUP(ORDER BY VAL) FROM RANK_TEST;

RANK(1) WITHIN GROUP(ORDER BY VAL)  RANK(2) WITHIN GROUP(ORDER BY VAL)

————————————————————-  ——————————————————-

1                                                                                  4

FIRST, LAST

aggregate_function KEEP (DENSE_RANK FIRST ORDER BY e1)

aggregate_function KEEP (DENSE_RANK LAST ORDER BY e1)

Verilmiş cədvəli e1-ə görə sıralayır, FIRST birinci qiyməti LAST sonuncu qiyməti saxlayır və aggregate_function-a bu qiyməti ötürür.

CREATE TABLE TEST_FL(A NUMBER(3));

INSERT INTO TEST_FL VALUES (1);

INSERT INTO TEST_FL VALUES (10);

INSERT INTO TEST_FL VALUES (3);

SELECT MAX(A) KEEP (DENSE_RANK FIRST ORDER BY A) FROM TEST_FL;

MAX(A) KEEP(DENSE_RANKFIRSTORDERBYA)

———————————————————-

1

SELECT MAX(A) KEEP (DENSE_RANK LAST ORDER BY A) FROM TEST_FL;

MAX(A) KEEP(DENSE_RANKFIRSTORDERBYA)

———————————————————-

10

GROUP BY

Sql sorğularımız daxilində aggregate funksiya istifadə etdiyimiz zaman GROUP BY ifadəsini mütləq olaraq işlətməliyik. Tək başına aggregate funksiya istifadə etdikdə istifadə etməyimizə gərək yoxdur. GROUP BY bizə cədvəldəki məlumatları verilmiş sütuna görə qrup halında emal etməyə kömək edir.

Misallarla izah etməyə çalışacağam, əsasə aşağıdakı cədvəl(ship_cabins) üzərində sorğular yazacağam.

SHIP_CABIN_ID ROOM_NUMBER ROOM_STYLE ROOM_TYPE WINDOW GUESTS SQ_FT
1 102 Suite Standard Ocean 4 533
2 103 Stateroom Standard Ocean 2 160
3 104 Suite Standard None 4 533
4 105 Stateroom Standard Ocean 3 205
5 106 Suite Standard None 6 586
6 107 Suite Royal Ocean 5 1524
7 108 Stateroom Large None 2 211
8 109 Stateroom Standard None 2 180
9 110 Stateroom Large None 2 225
10 702 Suite Presidential None 5 1142
11 703 Suite Royal Ocean 5 1745
12 704 Suite Skyloft Ocean 8 722

SELECT                 ROOM_STYLE,

                               ROUND(AVG(SQ_FT),2) “Average SQ FT”,

                               MIN(GUESTS) “Minimum # of Guests”,

                               COUNT(SHIP_CABIN_ID) “Total # of cabins”

FROM                   SHIP_CABINS

WHERE                SHIP_ID = 1

GROUP BY          ROOM_STYLE;

ROOM_STYLE   Average SQ FT      Minimum # of Guests    Total # of cabins

———————-  —————————-  ————————————  ———————-

Suite                  969.29                     4                                          7

Stateroom        196.2                       2                                          5

SELECT                  ROOM_TYPE,

                                TO_CHAR(ROUND(AVG(SQ_FT),2),’999,999.99′) “Average SQ FT”,

                                MAX(GUESTS) “Maximum # of Guests”,

                                COUNT(SHIP_CABIN_ID) “Total # of cabins”

FROM                   SHIP_CABINS

WHERE                 SHIP_ID = 1

GROUP BY          ROOM_TYPE

ORDER BY            2 DESC;

ROOM_TYPE       Average SQ FT  Maximum # of Guests   Total # of cabins

———————–  ————————  ———————————-  ———————-

Royal                   1,634.50              5                                         2

Presidential        1,142.00              5                                         1

Skyloft                 722.00                 8                                         1

Standard             366.17                 6                                         6

Large                   218.00                 2                                          2

SELECT                  ROOM_STYLE,

                                 ROOM_TYPE,

                                 TO_CHAR(MIN(SQ_FT),’9,999′) “Min”,

                                 TO_CHAR(MAX(SQ_FT),’9,999′) “Max”,

                                 TO_CHAR(MIN(SQ_FT)-MAX(SQ_FT),’9,999′) “Diff”

FROM                     SHIP_CABINS

WHERE                  SHIP_ID = 1

GROUP BY            ROOM_STYLE, ROOM_TYPE

ORDER BY            3;

ROOM_STYLE  ROOM_TYPE      Min     Max     Diff

———————-  ———————– ——–  ——–  ——

Stateroom        Standard            160      205       -45

Stateroom        Large                   211      225      -14

Suite                  Standard             533      586      -53

Suite                  Skyloft                 722      722         0

Suite                  Presidential        1,142  1,142      0

Suite                  Royal                   1,524  1,745   -221

Qeyd: Aggregate funksiyaları ancaq 2 səviyəyə qədər iç-içə(nested) istifadə edə bilərsiniz əks halda xəta alacaqsınız. Məs:

1)

SELECT                 AVG(MAX(SQ_FT))

FROM                    SHIP_CABINS

WHERE                 SHIP_ID = 1

GROUP BY           ROOM_STYLE, ROOM_TYPE;

 

2)

SELECT               COUNT(AVG(MAX(SQ_FT)))

FROM                   SHIP_CABINS

WHERE                SHIP_ID = 1

GROUP BY          ROOM_STYLE, ROOM_TYPE;

 

1ci sorğu heç bir xəta qaytarmayacaq ancaq 2ci sorğu bizə belə bir xəta qaytaracaq.

Error report:

SQL Error: ORA-00935: group function is nested too deeply 

00935. 00000  – “group function is nested too deeply”

HAVING

Sorğularımızda GROUP BY istifadə etdiyimiz zaman gruplaşdırılmış məlumatlara hər hansı şərt vermək istəyiriksə bu zaman WHERE yox HAVING ifadəsini istifadə etməliyik. HAVING ancaq və ancaq GROUP BY istifadə olunduğu zaman işlədilir.

Aşağıdakı şəkildə sql SELECT sorğularımızda hansı ifadələrin məcburi hansıların əlavə olduğu verilib.

SELECT                 ROOM_STYLE, ROOM_TYPE,

                               TO_CHAR(MIN(SQ_FT),’9,999′) “Min”

FROM                   SHIP_CABINS

WHERE                SHIP_ID = 1

GROUP BY          ROOM_STYLE, ROOM_TYPE

HAVING               ROOM_TYPE IN (‘Standard’, ‘Large’)

OR MIN(SQ_FT) > 1200

ORDER BY            3;

ROOM_STYLE  ROOM_TYPE       Min

———————-  ————————  ——

Stateroom        Standard              160

Stateroom        Large                    211

Suite                  Standard              533

Suite                  Royal                 1,524

Bir yazımızın daha sonuna gəldik, ümid edirəm faydalı olacaq, fikirlərinizi şərh yazaraq bildirin dostlar J