Anda di halaman 1dari 18

HIERARKY QUERY

Query Hierarky bias digunakan untuk membantu kita dalam menampilkan data
pegawai dalam suatu struktur hierarky. Dengan struktur hierarky kita lebih mudah
mengetahui komposisi pegawai.
Contoh Query Hierarky kita dapat menggunakan taabel pegawai dengan data
berikut ini :

Dari data diatas sebenarnya terlihat adanya hubungan antara kolom manager_id
dengan kolom id_pegawai. Hubungan kedua kolom tersebut menunjukkan
hubungan antara atasan dan bawahan. Sebagai contoh Meutia (1001) punya
bawahan langsung pegawai 1002, 1003, 1004, dan 1005 yaitu (Budi, Rully, Edwin
dan Novi) tetapi kita akan sulit membaca hal itu karena tampilan data tidak
berbentuk. Jika digambarkan maka struktur hierarki pegawai akan terlihat pada
gambar diatas.

Sebagaimana terlihat pada gambar diatas, elemen atau node tersebut membentuk
struktur hierarki. Node yang ada bisa kita menjadi bagi :

Root mode, yaitu merupakan puncak dari struktur hirarki, pada contoh di
gambar ini 10.1 sebagai root node adalah meutia J.M, yang artinya Meutia

J.M merupakan pimpinan dari organisasi tersebut.


Parent nide, node yang masih mempuyai node dibawahnya. Contohnya
adalah Meutia J.M adalah parent node dari Budi, Rulley, Edwin dan Novi.

Aris Mursito parent node dari Lia Nurlita dan Heru Kutanto.
Child node, node yang mempuyai parent node diatasnya. Contohnya Lia

Nurlita dan Heru Kutanto.


Leaf nade, nade yang tidak mempunyai child node. Contohnya adalah
Asfianti dan Suprayogi.

Juga dapat menggunakan perintak SELECT dengan klausa CONNECT BY dan


START WITH untuk membentuk query hararki.

A MEMFORMAT HASIL QUERY HIERARKI


Untuk menampilkan hasil query hierarki menjadi lebih jelas kita bisa
menggunakan pseudocolumn LEVEL pada single-jow function LPAD. Dengan
menggunakan LEVELpada fungsi LPAD kita bisa menampilkan struktur
hierarki dalam bentuk indentasi, dimana level yang lebih besar atau child node
akan ditampilkan lebih menjorok ke dalam dari pada parent node. Berikut ini
query menggunakan LPAD dan LEVEL untuk menghasilkan indentasi
berdasarkan level dari setiap data padastruktur query hierarki LPAD
(nama_pegawai)+2* LEVEL -1).
Bagaimana query tersebut bisa menghasilkan indentasi? Mari kita lihat
prosesnya. Lihat data pada MEUTIA JOVI MAHARANI, dia mempunya level
1 dan panjang namanya adalah 20 karakter, dari data tersebut kita bisa lihat
space yang dipean untuk nama MEUTIA JOVI MAHARANI adalah
20+2*1=21. Fungsi LPAD yang terjadi adalah LPAD (MEUTIA JOVI
MAHARANI), dengan ekpresi seperti diatas sebenarnya untuk pegawai yang
punya LEVEL 1 akan ditampilkan menjorok kedalam sebesar satu space.
Dengan cara yang sama, kita bisa dapatkan bahwa pegawai dengan LEVEL 2
akan ditampilkan menjorok kedalam sebanyak 3 space, LEVEL 3 menjorok ke
dalam sebanyak5 space, dan LEVEL 4 akan menjorok sebanyak 7 space.

Menampilkan satu Node atau Cabang


Jika kita ingin menampilkan salah satu node atau cabang maka yang harus
diganti adalah kondisi pada klausa START WITH. Misal kita akan
menampilkan struktur hierarki yang ada dibawah pegawai WIRA AULIA
maka klausa START WITH menjadi START WITH nama_pegawai =
WIRA AULIA, perintahnya lengkap sebagai berikut:

Top-Down dan Bottom-Up


Secara umum struktur hierarki menampilkan data mulai dari puncak
pimpinan sampai ke bawahan yang paling rendah. Gambaran seperti ini
disebut sebagai model top-down. Sedangkan pola yang dimulai dari
pegawai yang paling rendah terus bergerak sampai ke puncak pimpinan
disebut pola bottom-up. Pola suatu struktur hierarki ditentukan oleh
kondisi yang ada di klausa CONNECT BY. Untuk menghasilkan top-down
maka query-nya CONNECT BY PRIOR id_pegawai = manager_id =
id_pegawai yaitu CONNECT BY PRIOR manager_id = id_pegawai.
Akan ditampilkan pola bottom-up mulai dari pegawai ASFIYANTI
dengan perintah berikut :

Menghilangkan Node atau Cabanf dari Struktur Hierarki


Dari struktur hierarki yang masih lengkap, kita bisa menghilangkan salah
satu node dengan menambahkan klausa WHERE pada query hierarki.
Misalkan kita tidak ingin menampilkan node RULLY SIANIPAR dari
struktur hierarki maka tambahkan kalusa WHERE nama_pegawai <>
RULLY SIANIPAR.

Node RULLY SIANIPAR tidak muncul, tetapi pegawai-pegawai yang ada


dibawah RULLY SIANIPAR mulai dari RIDWAN SANUSI sampai ESTI
ARVINA tetap ditampilkan. Untuk menghilankan satu node sebagai
cabang yang ada dibawahnya tambahkan kondisi di CONNECT BY
PRIOR seperti berikut:

hierarchical_query_clause::=

MULAI DENGAN menentukan baris ( root) dari hirarki. CONNECT BY


menentukan hubungan antara baris orangtua dan baris anak hirarki.

Parameter NOCYCLE menginstruksikan Oracle Database untuk kembali


baris dari query bahkan jika CONNECT BY LOOP ada dalam data.
Gunakan

parameter

ini

bersama

dengan

pseudocolumn

CONNECT_BY_ISCYCLE untuk melihat baris yang berisi loop. Silakan


lihat CONNECT_BY_ISCYCLE Pseudocolumn untuk informasi lebih

lanjut.
Dalam query hirarkis, satu ekspresi dalam kondisi harus memenuhi syarat
dengan operator PRIOR untuk merujuk ke baris induk. Sebagai contoh,

Jika kondisi CONNECT BY adalah senyawa, maka hanya satu syarat


membutuhkan operator PRIOR, meskipun Anda dapat memiliki beberapa
kondisi PRIOR. Sebagai contoh:

PRIOR adalah operator unary dan memiliki prioritas yang sama dengan +
unary dan - operator aritmatika. Mengevaluasi ekspresi segera setelah
untuk

baris

induk

dari

baris

saat

ini

dalam

query

hirarkis.

PRIOR ini paling sering digunakan ketika membandingkan nilai kolom


dengan operator kesetaraan. (Kata kunci SEBELUM dapat di kedua sisi
operator.) PRIOR menyebabkan Oracle untuk menggunakan nilai baris
orangtua dalam kolom. Operator selain tanda sama dengan (=) secara
teoritis mungkin dalam CONNECT BY klausa. Namun, kondisi yang
diciptakan oleh para operator lainnya dapat mengakibatkan loop tak
terbatas melalui kombinasi yang mungkin. Dalam hal ini Oracle

mendeteksi loop pada run time dan kembali kesalahan.


Kedua kondisi CONNECT BY dan ekspresi PRIOR dapat mengambil
bentuk subquery berkorelasi. Namun, ekspresi PRIOR tidak bisa merujuk
ke urutan. Artinya, CURRVAL dan NEXTVAL tidak ekspresi PRIOR

valid.
Anda dapat lebih menyempurnakan query hirarkis dengan menggunakan
operator CONNECT_BY_ROOT untuk memenuhi syarat kolom dalam
daftar pilih. Operator ini memperluas fungsionalitas dari CONNECT BY

[PRIOR] kondisi query hirarkis dengan kembali tidak hanya orang tua
baris langsung tetapi semua baris leluhur dalam hirarki.

Oracle memproses query hirarkis sebagai berikut:

A bergabung, jika ada, maka dievaluasi dulu, apakah dapat dgabung lalu

ditentukan dalam klausa FROM atau dengan MANA predikat klausa.


Kondisi CONNECT BY dievaluasi.
Setiap tersisa MANA predikat klausa dievaluasi.

Oracle kemudian menggunakan informasi dari evaluasi tersebut untuk membentuk


hirarki menggunakan langkah-langkah berikut:

Oracle memilih akar baris (s) dari hirarki - baris yang memenuhi MULAI

DENGAN kondisi.
Oracle memilih baris anak setiap baris root. Setiap baris anak harus
memenuhi kondisi CONNECT BY kondisi sehubungan dengan salah satu

baris root.
Oracle memilih generasi-generasi baris anak. Oracle pertama memilih
anak-anak dari baris yang dikembalikan pada langkah 2, dan kemudian
anak-anak dari anak-anak, dan sebagainya. Oracle selalu memilih anakanak dengan mengevaluasi CONNECT BY kondisi sehubungan dengan

deretan orang tua saat ini.


Jika query berisi klausul MANA tanpa bergabung, maka Oracle
menghilangkan semua baris dari hirarki yang tidak memenuhi kondisi
klausa WHERE. Oracle mengevaluasi kondisi ini untuk setiap baris secara
individual, bukan menghapus semua anak-anak dari baris yang tidak

memenuhi kondisi tersebut.


Oracle mengembalikan baris dalam urutan yang ditunjukkan pada Gambar
9-1. Dalam diagram, anak-anak tampil di bawah orang tua mereka. Untuk
penjelasan dari pohon hirarkis

Contoh Kasus Hierarki Query


1

Contoh 1

CONNECT

BY

Example The

following

hierarchical

query

uses

the CONNECT BY clause to define the relationship between employees and


managers:
SELECT employee_id, last_name, manager_id
FROM employees
CONNECT BY PRIOR employee_id = manager_id;

EMPLOYEE_ID LAST_NAME

MANAGER_ID

----------- ------------------------- ---------101 Kochhar

100

108 Greenberg

101

109 Faviet

108

110 Chen

108

111 Sciarra

108

112 Urman

108

113 Popp

108

200 Whalen

101

...

LEVEL Example The next example is similar to the preceding example, but
uses the LEVEL pseudocolumn to show parent and child rows:
SELECT employee_id, last_name, manager_id, LEVEL
FROM employees
CONNECT BY PRIOR employee_id = manager_id;

EMPLOYEE_ID LAST_NAME

MANAGER_ID

LEVEL

----------- ------------------------- ---------- ----------

...

101 Kochhar

100

108 Greenberg

101

109 Faviet

108

110 Chen

108

111 Sciarra

108

112 Urman

108

113 Popp

108

START WITH Examples The next example adds a START WITH clause to
specify a root row for the hierarchy and an ORDER BY clause using
the SIBLINGS keyword to preserve ordering within the hierarchy:
SELECT last_name, employee_id, manager_id, LEVEL
FROM employees
START WITH employee_id = 100
CONNECT BY PRIOR employee_id = manager_id
ORDER SIBLINGS BY last_name;

LAST_NAME

EMPLOYEE_ID MANAGER_ID

LEVEL

------------------------- ----------- ---------- ---------King

100

Cambrault

148

100

Bates

172

148

Bloom

169

148

Fox

170

148

Kumar

173

148

Ozer

168

148

Smith

171

148

De Haan

102

100

Hunold

103

102

Austin

105

103

Ernst

104

103

Lorentz

107

103

Pataballa

106

103

Errazuriz

147

100

Ande

166

147

Banda

167

147

The NOCYCLE parameter in the CONNECT BY condition causes Oracle to


return the rows in spite of the loop.
The CONNECT_BY_ISCYCLEpseudocolumn shows you which rows
contain the cycle:
SELECT last_name "Employee", CONNECT_BY_ISCYCLE "Cycle",
LEVEL, SYS_CONNECT_BY_PATH(last_name, '/') "Path"
FROM employees
WHERE level <= 3 AND department_id = 80
START WITH last_name = 'King'
CONNECT BY NOCYCLE PRIOR employee_id = manager_id AND LEVEL
<= 4;

Employee

Cycle

LEVEL Path

------------------------- ------ -----------------------------Russell

2 /King/Russell

Tucker

3 /King/Russell/Tucker

Bernstein

3 /King/Russell/Bernstein

Hall

3 /King/Russell/Hall

Olsen

3 /King/Russell/Olsen

Cambrault

3 /King/Russell/Cambrault

Tuvault

3 /King/Russell/Tuvault

Partners

2 /King/Partners

King

3 /King/Partners/King

Sully

3 /King/Partners/Sully

McEwen

3 /King/Partners/McEwen

...

CONNECT_BY_ROOT Examples The following example returns the last


name of each employee in department 110, each manager above that employee
in the hierarchy, the number of levels between manager and employee, and the
path between the two:
SELECT last_name "Employee", CONNECT_BY_ROOT last_name
"Manager",
LEVEL-1 "Pathlen", SYS_CONNECT_BY_PATH(last_name, '/')
"Path"
FROM employees
WHERE LEVEL > 1 and department_id = 110
CONNECT BY PRIOR employee_id = manager_id;

Employee

Manager

Pathlen Path

--------------- ------------ -------------------------------------------Higgins

Kochhar

1 /Kochhar/Higgins

Gietz

Kochhar

2 /Kochhar/Higgins/Gietz

Gietz

Higgins

1 /Higgins/Gietz

Higgins

King

2 /King/Kochhar/Higgins

Gietz

King

/King/Kochhar/Higgins/Gietz

The following example uses a GROUP BY clause to return the total salary of
each employee in department 110 and all employees below that employee in
the hierarchy:
SELECT name, SUM(salary) "Total_Salary" FROM (
SELECT CONNECT_BY_ROOT last_name as name, Salary
FROM employees
WHERE department_id = 110
CONNECT BY PRIOR employee_id = manager_id)
GROUP BY name;

NAME

Total_Salary

------------------------- -----------Gietz

8300

Higgins

20300

King

20300

Kochhar

20300

2 Contoh 2( hirarki query kode akun


accounting)

CREATE TABLE `account` (


`accountId` int(11) NOT NULL AUTO_INCREMENT,
`parentId` int(11) DEFAULT NULL,
`accountName` char(20) NOT NULL,
PRIMARY KEY (`accountId`)
);
INSERT INTO `account` (`accountId`, `parentId`, `accountName`)
VALUES
(1, 0, 'Harta'),

(2, 1, 'Harta Lancar'),

(3, 2, 'Kas'),

(4, 2, 'Bank'),

(5, 2, 'Piutang Teman'),

(6, 1, 'Harta

Tetap'),
(7, 6, 'Kendaraan'),

(8, 7, 'Vario Matic'),

(9, 6, 'Product Electronic'),


(11, 0, 'Pendapatan'),
(13, 12, 'Gaji gue'),

(10, 6, 'Investasi'),

(12, 11, 'Gaji'),


(14, 11, 'Hasil Investasi');

SELECT * FROM account;

+-----------+----------+--------------------+
| accountId | parentId | accountName

+-----------+----------+--------------------+
|

1 |

0 | Harta

2 |

1 | Harta Lancar

3 |

2 | Kas

4 |

2 | Bank

5 |

2 | Piutang Teman

6 |

1 | Harta Tetap

7 |

6 | Kendaraan

8 |

7 | Vario Matic

9 |

6 | Product Electronic |

10 |

6 | Investasi

11 |

0 | Pendapatan

12 |

11 | Gaji

13 |

12 | Gaji gue

14 |

11 | Hasil Investasi

+-----------+----------+--------------------+
14 rows in set (0.00 sec)

Pada

hasil

dari SELECT diatas,

bahwa

tiap

item

pada

tabel

berisi parentId yang menunjuk ke parentnya. pada baris pertama


dan 11 berisi 0. Ini berarti row tersebut tidak mempunyai parent
atau bisa disebut sebagai parent itu sendiri. Model tabel diatas bisa
diterjemahkan Vario

Matic adalah

dari Kendaraan, Kendaraan adalah

child

child

dari Harta

Tetap dan Harta Tetap adalah child dari Harta yang mana tidak
mempunyai parent lagi alias parent itu sendiri. Walaupun tabel
diatas sudah dapat diterjemahkan, tetapi masih dibutuhkan suatu
query statement agar tampilan data collection lebih mudah untuk
dilihat/dimengerti.
Untuk menampilkan data tersebut dapat kita gunakan LEFT
JOIN :
mysql> SELECT a1.accountName AS Parent, a2.accountName as
Child1,
->

a3.accountName as Child2, a4.accountName as Child3

->

FROM account AS a1

->

LEFT JOIN account AS a2 ON a2.parentId = a1.accountId

->

LEFT JOIN account AS a3 ON a3.parentId = a2.accountId

->

LEFT JOIN account AS a4 ON a4.parentId = a3.accountId

->

WHERE a1.parentId =0;

+------------+-----------------+-------------------+-------------+
| Parent
Child3

| Child1

| Child2

+------------+-----------------+-------------------+-------------+
| Harta

| Harta Lancar

| Kas

| NULL

| Harta Lancar

| Bank

| NULL

| Harta Lancar

| Piutang Teman

| NULL

|
| Harta
|
| Harta
|

| Harta

| Harta Tetap

| Kendaraan

| Vario

| Harta Tetap

| Product Electronic | NULL

| Harta Tetap

| Investasi

| NULL

| Gaji gue

| NULL

Matic |
| Harta
|
| Harta
|
| Pendapatan | Gaji
|
| Pendapatan | Hasil Investasi | NULL

| NULL

+------------+-----------------+-------------------+-------------+
8 rows in set (0.00 sec)

Untuk menampilkan data account yang paling bawah atau account yang
tidak mempunyai child, saya menggunakan LEFT JOIN:
mysql> SELECT aOne.accountName FROM
-> account AS aOne LEFT JOIN account as aTwo
-> ON aOne.accountId = aTwo.parentId
-> WHERE aTwo.accountId IS NULL;
+--------------------+
| accountName

+--------------------+
| Kas

| Bank

| Piutang Teman

| Vario Matic

| Product Electronic |
| Investasi

| Gaji gue

| Hasil Investasi

+--------------------+
8 rows in set (0.00 sec)

Anda mungkin juga menyukai