Displaying Data from Multiple Tables

Salam, Bloguma xoş gəlmisiniz.

Bu yazımda sizlərə ORACLE SQL-in ən önəmli mövzularında olan JOIN-lərdən bəhs edəcəyəm. Məhz bu JOIN-lərə görə ORACLE “Relational Database Management System” adlanır. Mövzumuz bu bölmələrdən ibarət olacaq:

  • Equijoins (= operatorunu istifadə edənlər)
  • Non-equijoins
  • INNER joins
  • OUTER joins
  • NATURAL joins
  • Self-joins
  • Cross-joins(Cartesian joins)

EQUIJOINSNon-EQUIJOINS

  • EQUIJOIN-lər cədvəlləri birləşdirdiyi zaman əsasən “=” operatorundan istifadə edir.
  • Non-EQUIJOIN – lər cədvəlləri birləşdirdiyi zaman “<, >” müqayisə operatorlarından istifadə edirlər. EQUIJOIN-lərdə məlumatlar hər hansı bir qiymətə bərabər olurdusa burada məlumatlar müəyyən bir aralığa aid olur.

INNER OUTER joins

  • INNER join verilmiş bərabərliyə əsasən cadvəllərdən ancaq bərabərliyi ödəyən məlumatları qaytarır.
  • OUTER join verilmis bərabərliyə əsasən cədvəllərdən həm bərabərliyi ödəyən həmdə ödəməyən məlumatları qaytarır.

INNER join

Misallar üzərində izah edəcəyəm.

İsifadə edəcəyimiz cədvəllərin məlumatları ilə birlikdə aşağıda qeyd edirəm.

PORTS cədvəli:

PORT_ID PORT_NAME
1 Baltimore
2 Charleston
3 Tampa
4 Miami

SHIPS cədəli:

SHIP_ID SHIP_NAME HOME_PORT_ID
1 Codd Crystal 1
2 Codd Elegance 3
3 Codd Champion
4 Codd Victorious 3
5 Codd Grandeur 2
6 Codd Prince 2

SELECT                  SHIP_ID,

                                SHIP_NAME,

                                PORT_NAME

FROM                    SHIPS  INNER JOIN PORTS

ON                          HOME_PORT_ID = PORT_ID

ORDER BY            SHIP_ID;

Qeyd: INNER sözü əlavədir yəni yazmasaqda sorğumuz düzgün işləyəcək.

Nəticə:

SHIP_ID     SHIP_NAME               PORT_NAME

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

1                Codd Crystal                Baltimore

2               Codd Elegance            Tampa

4               Codd Victorious          Tampa

5               Codd Grandeur           Charleston

6               Codd Prince                 Charleston

Qeyd: Nəticədən göründüyü kimi  id-si 3, adı “Codd Champion” olan ship nəticədə çıxmadı çünki INNER join ancaq və ancaq “ON” şərtində verilən bərabərlik ödənildikdə nəticə verir.

Join-lərdə də digər sql sorğular kimi WHERE ifadəsini istifadə edə bilərik, tək qayda “ON” ifadəsindən sonra işlədilməlidir.

Məs:

SELECT                 SHIP_ID,

                                SHIP_NAME,

                                PORT_NAME

FROM                    SHIPS INNER JOIN PORTS

ON                         HOME_PORT_ID = PORT_ID

WHERE                 PORT_NAME = ‘Charleston’

ORDER BY            SHIP_ID;

Nəticə:

SHIP_ID     SHIP_NAME               PORT_NAME

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

5               Codd Grandeur          Charleston

6               Codd Prince                Charleston 

Qeyd: INNER join –lər yazmağın bir digər üsulu isə ORACLE-ın əvvəlki versiyalarında istifadə etdiyi və hal hazırda da işlək olan üsuldur:

SELECT                  S.SHIP_ID,

                                 S.SHIP_NAME,

                                P.PORT_NAME

FROM                    SHIPS S, PORTS P

WHERE                 S.HOME_PORT_ID = P.PORT_ID

ORDER BY            S.SHIP_ID;

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

SELECT                  S.SHIP_ID,

                                 S.SHIP_NAME,

                                 P.PORT_NAME

FROM                    SHIPS S, PORTS P

WHERE                 S.HOME_PORT_ID = P.PORT_ID

AND                       PORT_NAME = ‘Charleston’

ORDER BY            S.SHIP_ID;         

Qeyd: Son 2 sorğuda istifadə etdiyimiz cədvəllərin yanına birdə “S”“P” yazdıq bunun yazmaq məqsədimiz cədvələ alians verərək hər dəfə cədvəlin tam adını yazmaqdan canımızı qurtarmaq idi,  bir növ cədvələ sorğu daxilində yeni ad təyin etmiş olduq. Alians-lar həm cədvəl adlarına həm sütun adlarına sorğu daxilində alternativ adlar verir və çox geniş istifadə olunur.

OUTER join

OUTER join-lər INNER joinlərdə olduğu kimi “ON” ifadəsindəki bərabərliyi ödəyən nəticələri bizə qaytarır ancaq əlavə olaraq bərabərliyi ödəməyən məlumatlarıda bizə qaytarır. 3 növü var:

  • LEFT OUTER JOIN(LEFT JOIN)
  • RIGHT OUTER JOIN(RIGHT JOIN)
  • FULL OUTER JOIN(FULL JOIN)

Qeyd: OUTER sözü əlavədir, sorğularda istifadə etsək də etməsək də nəticəyə təsir etmir.

LEFT OUTER JOIN(LEFT JOIN)

LEFT join sintaksisində LEFT-dən solda yazılmış cədvəlin bütün sətirlərini və o sətirlərə sağdakı cədvəldən uyğun gələn sətirləri qaytarır.

Yenə SHIPSPORTS cədvəllərinə baxaq və bu cədvəllər üzərində LEFT join yaradaq.

SELECT                  SHIP_ID,

                                SHIP_NAME,

                                PORT_NAME

FROM                    SHIPS LEFT OUTER JOIN PORTS

ON                         HOME_PORT_ID = PORT_ID

ORDER BY            SHIP_ID;

Nəticə:

SHIP_ID     SHIP_NAME               PORT_NAME

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

1                Codd Crystal                Baltimore

2                Codd Elegance           Tampa

3                Codd Champion

4                Codd Victorious          Tampa

5                Codd Grandeur           Charleston

6                Codd Prince                 Charleston

Nəticədən də gördüyümüz kimi SHIPS cədvəlinin bütün sətirləri saxlanıldı və onlara uyğun nəticələr qaytarıldı, uyğun olmayanlar isə NULL qaytarılacaq. Gəlin biz bu NULL ifadələri əvvəl öyrəndiyimiz bir funksiya ilə dəyişək və nəticəni daha anlaşıqlı edək.

SELECT                  SHIP_ID,

                               SHIP_NAME,

                               NVL(PORT_NAME, ‘-‘)

FROM                   SHIPS LEFT OUTER JOIN PORTS

ON                         HOME_PORT_ID = PORT_ID

ORDER BY            SHIP_ID;

Nəticə:

SHIP_ID     SHIP_NAME               PORT_NAME

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

1                Codd Crystal                Baltimore

2                Codd Elegance           Tampa

3                Codd Champion          –

4                Codd Victorious          Tampa

5                Codd Grandeur           Charleston

6                Codd Prince                 Charleston

RIGHT OUTER JOIN(RIGHT JOIN)

RIGHT join sintaksisində RIGHT-dən sağda yazılmış cədvəlin bütün sətirlərini və o sətirlərə soldakı cədvəldən uyğun gələn sətirləri qaytarır.

Yenə SHIPSPORTS cədvəllərinə baxaq və bu cədvəllər üzərində RIGHT join yaradaq.

SELECT                  SHIP_ID,

                                SHIP_NAME,

                                PORT_NAME

FROM                    SHIPS RIGHT OUTER JOIN PORTS

ON                         HOME_PORT_ID = PORT_ID

ORDER BY            SHIP_ID;

Nəticə:

SHIP_ID     SHIP_NAME               PORT_NAME

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

1                Codd Crystal                  Baltimore

2               Codd Elegance              Tampa

4               Codd Victorious             Tampa

5               Codd Grandeur              Charleston

6               Codd Prince                   Charleston

                                                           Miami

SELECT                  NVL(SHIP_ID, ‘-‘),

                                 NVL(SHIP_NAME, ‘-‘),

                                 PORT_NAME

FROM                    SHIPS RIGHT OUTER JOIN PORTS

ON                         HOME_PORT_ID = PORT_ID

ORDER BY            SHIP_ID;

Nəticə:

SHIP_ID     SHIP_NAME               PORT_NAME

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

1                Codd Crystal                  Baltimore

2               Codd Elegance              Tampa

4               Codd Victorious             Tampa

5               Codd Grandeur              Charleston

6               Codd Prince                    Charleston

–                              –                          Miami

FULL OUTER JOIN(FULL JOIN)

FULL OUTER JOIN  =  RIGHT OUTER JOIN + LEFT OUTER JOIN.

SELECT                  SHIP_ID,

                                SHIP_NAME,

                                PORT_NAME

FROM                    SHIPS FULL OUTER JOIN PORTS

ON                         HOME_PORT_ID = PORT_ID

ORDER BY            SHIP_ID;

Nəticə:

SHIP_ID     SHIP_NAME               PORT_NAME

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

1               Codd Crystal                  Baltimore

2              Codd Elegance              Tampa

3              Codd Champion

4              Codd Victorious            Tampa

5              Codd Grandeur            Charleston

6              Codd Prince                  Charleston

                                                         Miami

SELECT                  NVL(SHIP_ID, ),

                                 NVL(SHIP_NAME, ),

                                 NVL(PORT_NAME, )

FROM                    SHIPS FULL OUTER JOIN PORTS

ON                         HOME_PORT_ID = PORT_ID

ORDER BY            SHIP_ID;

Nəticə:

SHIP_ID     SHIP_NAME               PORT_NAME

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

1               Codd Crystal                  Baltimore

2              Codd Elegance              Tampa

3              Codd Champion             –

4              Codd Victorious            Tampa

5              Codd Grandeur            Charleston

6              Codd Prince                  Charleston

 –              –                                      Miami

Qeyd: Bir digər OUTER join yaratmaq üsulu isə bu şəkildədir. (+) sağda olarsa LEFT OUTER JOIN, solda olarsa RIGHT OUTER JOIN olaraq işləyir. Oracle bu şəkildə yazılışı tövsiyə etmir ancaq hələdə işlək bir sintaksis olaraq istifadə olunur bu üsul.

SELECT                  SHIP_ID,

                                 SHIP_NAME,

                                 PORT_NAME

FROM                    SHIPS, PORTS

WHERE                 HOME_PORT_ID = PORT_ID(+)

ORDER BY            SHIP_ID;

NATURAL join

İndiyə kimi baxdığımız join-lərdə primary key(PK) və foreign key(FK) –lərin aid olduğu sütunlar fərqli adlarda(HOME_PORT_ID, PORT_ID) idi, birdə bu constraintlərin aid olduğu sütunlar eyni adda olduğu zaman istifadə etidiyimiz join növü var hansıki NATURAL join adlanır.

Məsələn EMPLOYEESADRESSES cədvəllərinin strukturuna baxdıqda PK və FK –nın eyni ada aid olduğunu görürük.

emp_adr_table

Bu cədvəlləri join etməyimiz üçün belə yazmağımız kifayətdir:

SELECT                  EMPLOYEE_ID,

                                 LAST_NAME,

                                 STREET_ADDRESS

FROM                     EMPLOYEES NATURAL JOIN ADDRESSES;

Qeyd: NATURAL join INNER join-dir yəni ancaq primary key-in qiymətinin foreign key qiymətinə bərabər olduğu zaman məlumat qaytarır. Həm OUTER həm INNER ola biləcək join-lər isə USING işlətməklə yazılır, aşağıda bundan bəhs edəcəyəm.

USING

USING eyni ilə NATURAL join kimi primary key və foreign key constraintlərinin sütun adları eyni olduğu zaman istifadə olunur. NATURAL joindən fərqi isə həm OUTER həm INNER join kimi istifadə oluna bilməsidir.

Yenə EMPLOYEESADDRESSES cədvəllərin istifadə edərək bu dəfə USING vasitəsilə join yaradaq.

SELECT                  EMPLOYEE_ID,

                                LAST_NAME,

                                STREET_ADDRESS

FROM                    EMPLOYEES LEFT JOIN ADDRESSES

USING                  (EMPLOYEE_ID);

MUTLITABLE join

İndiyə kimi ancaq 2 cədvəlin birləşdirilməsinə baxdıq ancaq 2dən çox 3,4,5 …n cədvəlidə birləşdirmək mümkündür.

Məsələn  strukturları bu şəkildəki kimi olan 3 cədvəli birləşdirilməsinə baxaq.

ships_ports_ship_cabins

SELECT                  P.PORT_NAME,

                                S.SHIP_NAME,

                                SC.ROOM_NUMBER

FROM                    PORTS P JOIN SHIPS S

ON                         P.PORT_ID = S.HOME_PORT_ID

JOIN                      SHIP_CABINS SC

ON                         S.SHIP_ID = SC.SHIP_ID;

Non-EQUIJOINS

Yazımın bu hissəsinə kimi ancaq “equijoin”-lərdən istifadə etdik yəni cədvəllərimizi hər hansı bir bərabərlik nəticəsində birləşdirib məlumat əldə etdik.

Non-equijoin-lər bizə bərabər(=) işarəsindən istifadə etmədən, onun yerinə müqayisə operatorlarında istifadə edərdək cədvəllərimizi birləşdirməyimizə yardım edir.

Bir misal üzərində izah edəcəyəm.

2 cədvəlimiz olsun. 1-də tələbələrin aldığı qiymətlər saxlayaq və adı “SCORES” olsun, 2-də hansı qiymət aralığının nəyi bildirdiyini saxlayaq və adı “GRADING” olsun. Bu şəkildə:

 

SCORE_ID TEST_SCORE
1 95
2 55
3 83

 

GRADING_ID        GRADE SCORE_MIN SCORE_MAX
1 A  90 100
2 B  80 89
3 C  70 79
4 D  60 69
5 E  50 59

SELECT                  S.SCORE_ID,

                                 S.TEST_SCORE,

                                G.GRADE

FROM                    SCORES S JOIN GRADING G

ON                         S.TEST_SCORE BETWEEN G.SCORE_MIN AND G.SCORE_MAX;   

Nəticə:

SCORE_ID  TEST_SCORE    GRADE

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

1                   95                     A

3                   83                     B

2                   55                     E

SELF-JOIN

Self join bir cədvəlin yenidən özünə join olunmasıdır. Self join-lər INNER, OUTER, EQUIJOIN, həmçinin NON-EQUIJOIN ola bilərlər.

Məsələn “POSITIONS” cədvəlimizi yenidən özünə birləşdirək.

 

POSITION_ID       POSITION         REPORTS_TO
1       Captain
2       Director          1
3       Manager          2
4       Crew Chief          2
5       Crew          4

Cədvəlimiz özünə birləşdirmək üçün foreign key constraint-inin olması tövsiyə olunur, ilk öncə foreign key –imizi yaradaq.

ALTER TABLE      POSITIONS

ADD                        CONSTRAINT FK_PO FOREIGN KEY (REPORTS_TO)

REFERENCES       POSITIONS (POSITION_ID);

İndi self join-imiz rahat bir şəkildə yaza bilərik.

SELECT                  A.POSITION_ID,

                                A.POSITION,

                                B.POSITION BOSS

FROM                    POSITIONS A LEFT OUTER JOIN POSITIONS B (eyni cədvələ fərqli 2 alians veririk)

ON                         A.REPORTS_TO = B.POSITION_ID

ORDER BY            A.POSITION_ID; 

POSITION_ID       POSITION              BOSS

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

1                            Captain

2                            Director                 Captain

3                            Manager               Director

4                            Crew Chief           Director

5                            Crew Crew           Chief

CROSS join

CROSS join həmçinin “CARTESİAN product” –da adlanır. Yazdığımız SELECT sorğularda heç bir join şərti istifadə etmədən 1dən çox cədvəldən məlumat aldığımız zaman baş verir cross join.

Cədvəllərimizin birində n digərində m sətir məlumat varsa biz cross join sonrası n*m sətir məlumat əldə edəcəyik.

Məsələn VENDORSSUBSCRIBERS cədvəllərini cross join edək.

VENDORS

VENDOR_ID VENDOR_NAME
1 Acme Steaks
2 Acme Poker Chips

SUBSCRIBERS

SUBSCRIBER_ID LASTNAME
1 KLINE
2 bryant
3 McLean

1)

SELECT                  *

FROM                   VENDORS, ONLINE_SUBSCRIBERS;

2)

SELECT                  *

FROM                   VENDORS CROSS JOIN ONLINE_SUBSCRIBERS;

1 və 2-ci sorğular bir birinə ekvivalentdir.

Nəticə:

VENDOR_ID        VENDOR_NAME       SUBSCRIBER_ID     LASTNAME

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

1                             Acme Steaks                1                               KLINE

1                             Acme Steaks                2                               bryant

1                             Acme Steaks                3                               McLean

2                             Acme Poker Chips      1                                KLINE

2                             Acme Poker Chips      2                                bryant

2                             Acme Poker Chips      3                                McLean

Qeyd: Oracle SQL – də cross join kimi bir xüsusiyyət olsa da bu join növünü tətbiqlərinizdə istifadə etmək heç də faydalı deyil və eyni zamanda tövsiyə olunmur, istifadəsinin yararlı olduğunu düşünən və ya sıx istifadə edən varsa şərh yazsın görək həqiqətən yararlı ola bilirmi cross join 🙂

 

Bu yazımda da bu qədər, ümid edirəm sizə faydalı bilgilər verə bildim, fikirlərinizi eyni zamanda tənqidlərinizi şərh yazaraq bildirin 🙂