Stromy a hierarchické struktury v SQL

Preview:

DESCRIPTION

Stromy a hierarchické struktury v SQL. 30.11.2005 Mária Szabó, Jirka Zouhar, Gergely Jakab. M ária Szabó 30 .11.2005. Using the Node Type to Solve Problems with Hierarchies in DB2 Universal Database. Node Type & Hierarchies in DB2. Z ákladní p ojmy Úvod do problematiky Koncept řešení - PowerPoint PPT Presentation

Citation preview

Stromy a hierarchické struktury v SQL

30.11.2005Mária Szabó, Jirka Zouhar, Gergely Jakab

Using the Node Type to Solve Problems with Hierarchies in

DB2 Universal Database

Mária Szabó 30.11.2005

Základní pojmy Úvod do problematiky Koncept řešení Node type Výhody Příklady

Node Type & Hierarchies in DB2

Node Type & Hierarchies in DB2

● Hiearchie● Relační Db● Node Type

Pojmy

Node Type & Hierarchies in DB2

● Před 30 lety – hierarchical db● Svázánost se db strukturou● Ukazatel – pointer● Nákladné chyby● Vícenásobné použití pro stejná data

Problematika

Node Type & Hierarchies in DB2

• Průměr účetní bilance pro každý region i odvětví

• 10 největších klientů

Definovat více hierarchií

Synchronizace dat

Node Type & Hierarchies in DB2

• Pre-processing dat• Myšlenka typu UZEL• Série čísel• Hladina – Level• Indexování jako v SQL

Uzel & Hierarchie

Node Type & Hierarchies in DB2

CREATE TABLE employee (Employee_Id Integer,Manager_Id Integer,Last_Name varchar(30)...PRIMARY KEY(Employee_Id),FOREIGN KEY (Manager_Id) REFERENCES employee(Employee_Id);Kolik zaměstnanců pracuje pro jistého managera?

SELECT COUNT (*) FROM employee emp, employee managerWHERE emp.Manager_Id = manager.Employee_IdAND manager.Last_Name = ‘Roy’;

Pro každého zaměstnance zjistit počet podřízených !?!

Node Type & Hierarchies in DB2

● Vícenásobné levely v managmentu● SQL příkaz pro každý manager pro

každý level● Víckrát vnořovat

Problém

CREATE TABLE employee2 (Employee_Id Node,Last_Name varchar(30),...PRIMARY KEY(Employee_Id);

Node Type & Hierarchies in DB2

1| |Joe|2|1|Joe2|. . .8|2|Joe8|. . .14|3|Joe14|

1.0|Joe|1.2|Joe2|. . .1.2.8|Joe8|. . .1.3.14|Joe14|

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

NULL na místě managera šéf

Node Type & Hierarchies in DB2

● Kolik zaměstnanců pracuje pod specifikovaným managerom?

1. Přímé potomky2. Rekurzie dokud jsme neprošli všechny

lidi3. Rekurzivní dotaz nebo procedura

WITH RPL (employee_Id, Manager_Id, Last_Name) AS (SELECT ROOT.employee_Id, ROOT.Manager_Id, ROOT.Last_Name FROM employee ROOT WHERE ROOT.employee_Id = 1 UNION ALL SELECT CHILD.EMployee_Id, CHILD.Manager_Id, CHILD.Last_Name FORM RPL PARENT, employee CHILD WHERE PARENT.Employee_Id = CHILD.Manager_Id )SELECT COUNT(*) -1FROM RPL;

Pro EMPLOYEE table:

Node Type & Hierarchies in DB2

● Kolik zaměstnanců pracuje pod špecifikovaným mangerom?

SELECT COUNT(*) FROM Employee2WHERE Employee_ID > NodeInput(‘1.2’)AND EMPLOYEE_ID < NodeInput(‘1.3’);

Pro EMPLOYEE2 table:1.3 > 1.2.8 > 1.2

• uzly, které padají pod spec. managerom

Node Type & Hierarchies in DB2

Úroveň Počet Rozdíl

2 6 1.0

3 42 1.8

4 258 8.4

5 1554 41

6 9330 37.75

Test• Každý manager 6 přímých potomků

• Lidi úplně na spodku nejsou managery

• pro 9331 řádků 37 násobné zrychlení• tradiční přístup exponenciální char.• uzlový přístup lineární charakteristika• rozdíl se zvětšuje #levelu

Node Type & Hierarchies in DB2

Ancestors(Node) GetMember(Node,integer) GetParent(Node)

Graft(Node,Node,Node) Increment(Node) Increment(Node,integer)

Graft(Node,Node,Node) IsChild(Node,Node) IsDescendant(Node,Node)

IsParent(Node.Node) Length(Node) NewLevel(Node)

NodeInput(varchar(180)) NodeOutput(Node)

Implementace typu UZEL - NODE

CREATE DISTINCT TYPE Node AS varchar(64)FOR BIT DATA WITH COMPARISONS;

Node Type & Hierarchies in DB2

Indexování a SQL dotazy

• indexování typu uzel• umístnit do WHERE klauzuli• možnost i bez indexování scan table

SELECT * FROM employee2WHERE isDescendant(employee_Id, NodeInput(‘1.7.43’))ORDER BY employee_Id Desc;

Příklad vrátí všechny potomky uzlu 1.7.43

Node Type & Hierarchies in DB2

Příklad vrátí všechny potomky uzlu 1.7.43

SELECT * FROM employee2WHERE employee_Id > NodeInput(‘1.7.43’)AND employee_Id < NodeInput(‘1.7.44’)ORDER BY employee_Id Desc;

Příklad vrátí pouze přímé potomky uzlu 1.7.43

SELECT * FROM employee2WHERE employee_Id > NodeInput(‘1.7.43’)AND employee_Id < NodeInput(‘1.7.44’)AND Length(employee_id) = 4ORDER BY employee_Id Desc;

Node Type & Hierarchies in DB2

!Občas je zapotřeby přidat funkce pro zachování použitelnosti indexu!

SELECT * FROM employee2WHERE isAncestor(employee_Id, NodeInput(‘1.7.43.256.1537’))ORDER BY employee_Id Desc;

1.7.43.256 , 1.7.43, 1.7, 1.0

SELECT * FROM Employee2WHERE Employee_Id IN ( SELECT x.col1 FROMTABLE(Ancestors(NodeInput(‘1.7.43.256.1537’))) AS x )ORDER BY employee_Id Desc;

Node Type & Hierarchies in DB2

Hlavní výnos

Obrovské tabulky rýchlá odezva

Rozumné dotazy nezávislost na # požadavků

Děkuji

Mária Szabó 30.11.2005

Detaily hierarchii v DB2

30.11.2005Jirka Zouhar

Použití● Ve složitějších případech je třeba oddělit

hierarchii od dat● Lze použít i více hierarchií

● Příklady:– Skladová evidence zásob– Hierarchické systémy zásad– Klasifikace objektů

Hierarchie zásad

● CREATE TABLE Policies (PolicyNumber Node,Description varchar(50) );

● CREATE TABLE Objects (Name varchar(50),PolicyNumber Node );

● CREATE TABLE Safe_places (Location Node,PolicyNumber Node,Description varchar(75),Administrator varchar(30) );

Hierarchie zásad● Jaké objekty mají „malé“ zabezpečení?● Jak zabezpečený je daný objekt?● Mají všechny zóny korektní zabezpečení?● Nejsou objekty v špatných zónách?

● SELECT * FROM Objects, Places WHERE Places.policyNumber NOT IN Ancestors(Objects.policyNumber)

Skladová evidence

● CREATE TABLE Parts (PartNumber integer,Name varchar(30),Price money );

● CREATE TABLE Components (ComponentId Node,Sequence integer,Quantity integer,Name varchar(30),PartNumber integer );

Klasifikace Objektů● CREATE TABLE materials (

– Name varchar(30),– Type Node );

● CREATE TABLE parts (– Name varchar(30),– Type node,– ComponentId node,– Price integer,– Provider varchar(30),– PartNumber ingeter,– Description integer );

Klasifikace objektů

1 Materiál

1.1.1 mahagon

1.2 železo1.1 dřevo 1.3 kůže

Klasifikace objektů● Najdi všechny součástky z mahagonu s

cenou menší padesáti.● SELECT name,desc,price FROM parts WHERE isDescendant(type, NodeInput( SELECT type FROM materials WHERE name='mahagon')) AND price < 50;

Funkce pro práci s Node Type● Node nodeInput (varchar)Převede varchar na Node Type.

● Varchar nodeOutput (node)Převede Node Type na Varchar

V dalším bude pro zjednodušení používán místo

nodeInput ('1.3.5') zjednodušený zápis 1.3.5

Funkce pro práci s Node Type● Node[] Ancestors (node)Vrátí seznam předků:Ancestors(1.25.3) = {1.25,1}

● Integer GetMember (Node, Integer)Vrátí číslo větve na dané úrovni:GetMember(1.3.5.4,2) = 3

● Node getParent (node)Vrátí otce zadaného:getParent(1.5.4) = 1.5

Funkce pro práci s Node Type● Node Increment (node)Vrátí další node v řadě:Incerment (1.2.22) = 1.2.23

● Node Increment (node, integer)Vrátí další node v řadě na dané úrovni:Increment (1.2.22, 2) = 1.3

● Node newLevel (node)Vrátí nový node o úroveň níž:newLevel (1.2) = 1.2.1

Funkce pro práci s Node Type● Integer isAncestor (node1, node2)Testuje, zda je node2 v podstromu node1:isAncestor (1.2, 1.2.3.55) = 1isAncestor (1.3, 1.2.4) = 0

● Integer isDescendant(node,node)Opak isAncestor:isDescendant (node1, node2) =isAncestor (node2, node1)

Funkce pro práci s Node Type● Integer isChild (node1, node2)Testuje, zda je node2 synem node1:isChild (1.2, 1.2.3) = 1isChild (1.2, 1.2.3.5) = 0

● Integer isParent (node, node)Opak isChild

● Integer length(node)Zjistí úroveň node ve stromu:length (1.2.3.5) = 4

Funkce pro práci s Node Type● Node graft(node,node,node)Přesune větev danou třetím parametrem jako

podstrom druhého parametru, první je otec přemísťovaného stromu.

UPDATE Parts SET Part_num = Graft( 1.2, 1.5.6, Part_num)WHERE Part_num > 1.2.18AND Part_num < 1.2.19

Funkce pro práci s Node Type● Graft (1.1.3, 1.4, 1.1.3.2) = 1.4.2

1.1.3.2

1

1.1.3

1.1 1.4

1.4.1 1.1.3 1.4.21.4.1

1.41.1

1

Zdroje● http://www3.software.ibm.com/ibmdl/pub/software/dw/dm/db2/0302roy/0302roy.pdf● http://www3.software.ibm.com/ibmdl/pub/software/dw/dm/db2/0302roy/DB2Node.zip

Hnízděné intervaly

30.11.2005

Gergely Jakab

Nested intervals

Obsah

● Úvod● Materializovaná cesta● Vnořené množiny

– vylepšení● Vnořené intervaly

– Základní myšlenka– Mapovaní– Normalizace– Funkce– Příklady: Test struktury

Úvod

● tranzitivní závislosti v relační databázi (hierarchické struktury)

● 4 dobře známé metody z nichž 2 prozkoumáme– materializovaná cesta– vnořené množiny

● Vadim Tropashko vymyslel smíšeninu těchto dvou metod (vnořené intervaly)

● implementace a příklady na Oracle

Skok zpátky : materializovaná cesta

● každý záznam obsahuje absolutní cestu k uzlu● cesta = čísla uzlů od kořene oddělené separátorem● jistá podobnost k absolutním cestám na UNIXu● kompaktnější verze místo primárního klíče uzlů staví

cestu z pořadového čísla uzlu mezi sourozenci

Dotazy u materializované cesty

ENAME PATHKING 1JONES 1.1SCOTT 1.1.1ADAMS 1.1.1.1FORD 1.1.2SMITH 1.1.2.1BLAKE 1.2ALLEN 1.2.1WARD 1.2.2CLARK 1.3MILLER 1.3.1

standardní dotazy s „LIKE“ :efektivní na podřízenéNEefektivní na nadřízené

chytré dotazování pro nadřízené:pomoci řetězcové funkce, která vrátí

množinu cest všech nadřízenýchf('1.2.1.1') = ('1.2.1', '1.2', '1')…WHERE super.path in f(this.path)

Vnořené množiny● uchovává globální pozici uzlu● pozice uzlu = 2 celé čísla definující interval

[left, right], který obsahuje všechny potomky● uzel p je předkem uzlu c právě když :

p.left <= c.left <= c.right <= p.right● nevýhody :

– dotazy na nadřízené (hledání intervalů obsahující daný bod)

– nestálá struktura – přidávání prvku ≈ přepočet půlku struktury

– vhodné pouze pro statické množiny

Albert (1,12)

Bert (2,3)

Chuck (4,11)

Donna (5,6)

Fred (9,10

)Eddy (7,8)

Vnořené množiny - vylepšení

● původní pravidlo :– každý uzel (s pozicí [left, right]) má přesně

(right - left - 1) / 2 potomků● vylepšení od Joe Celko :

– vypuštěním výše uvedeného pravidla nechat větší

mezery mezi left a right pro přidávané potomky● nepomůže, pokud left a right můžou být pouze celá čísla,

protože za nějakou dobu se zaplní libovolně velká mezera

Vnořené intervaly - definice● jde o zobecnění vnořených množin● hranice intervalů již nemusí být celá čísla

– potřebujeme hustší doménu– podle potřeby můžou být racionální nebo reálné

čísla● nadále platí : uzel p je předkem uzlu c právě když

p.left <= c.left <= c.right <= p.right● je několik způsobů jak umístit do struktury nový uzel

Vnořené intervaly - 1.způsob● najdeme volný úsek <left1,right1> uvnitř intervalu rodiče● pak vkládaný uzel bude

[(2*left1 + right1)/3, (left1 + 2*right1)/3]● a pro další potomky toho rodiče ještě jsou k dispozici :

<left1, (2*left1 + right1)/3> a <(left1 + 2*right1)/3, right1>

p.left left1 2*left1 + right1)/3 (left1 + 2*right1)/3 right1 p.right

Vnořené intervaly - 2.způsob

● 2-dimenzionální model :– osa x je right– osa y je left

● relace „býti podmnožinou“

je částečné uspořádání

y

x1

1.1

1.2

1.3

Vnořené intervaly - mapování

● kořen zvolíme libovolně, např. [0,1]● každý uzel pak reprezentuje jeden

pravoúhlý trojúhelník pod diagonálou● definujeme 2 důležité body:

– bod konvergence do hloubky● průsečík diagonály a vertikály

protínající uzel– bod konvergence do šířky

● průsečík diagonály a horizontály protínající uzel

y

x1

1.1

b.k. do hloubky

b.k. do šířky

Vnořené intervaly - mapování2● pro každý uzel pozice jeho :

– prvního syna je v polovině

úsečky mezi uzlem a b.k. do

hloubky– dalších synů je v polovině

úsečky mezi předchozím

synem a b.k. do šířky● např.: uzel 1.2 je [ ¼ , ½ ]

Vnořené intervaly - symetrie

● naše hustá doména nebude doména reálných ani racionálních čísel, ale doména dvojic zlomků

● symetrie – každý

podstrom má stejnou

strukturu– syn je zmenšený rodič– obdoba fraktálů

Vnořené intervaly - normalizace

● kvůli zmíněné symetrie souřadnice uzlu nejsou na sobě nezávislé

● z jejich sumy lze vypočítat složky x a y● namísto dvojic zlomků stačí pamatovat součet dvojic,

tj. jeden zlomek, tj. 2 celá čísla● tím jsme se dostali na úroveň vnořených množin v

množství uchovávaných dat na jeden uzel

Vnořené intervaly - normalizace

function x_numer( numer integer, denom integer ) RETURN integer ISret_num integer; ret_den integer;

BEGINret_num := numer+1; -- posun svisle nahoru na diagonáluret_den := denom*2; -- souřadnice x je polovina podíluwhile floor(ret_num/2) = ret_num/2 loop -- redukce zlomku

ret_num := ret_num/2;ret_den := ret_den/2;

end loop;RETURN ret_num; -- pro čitatel-- RETURN ret_den; -- pro jmenovatel ve funkci x_denom()

END;

Vnořené intervaly - normalizacefunction y_numer( numer integer, denom integer ) RETURN integer IS

ret_num integer; ret_den integer;BEGIN

ret_num := x_numer(numer, denom); -- získání čitatele xret_den := x_denom(numer, denom); -- získání jmenovatele xwhile den < denom loop -- převést na společný jmenovatel

ret_num := ret_num*2; ret_den := ret_den*2;end loop;ret_num := numer – ret_num; -- získat čitatel ywhile floor(ret_num/2) = ret_num/2 loop -- redukce zlomku

ret_num := ret_num/2; ret_den := ret_den/2;end loop;RETURN ret_num; -- pro čitatel

END; -- RETURN ret_den; -- pro jmenovatel ve funkci y_denom()

Vnořené intervaly - příklad1

SELECT x_numer(39,32) || '/' || x_denom(39,32),y_numer(39,32) || '/' || y_denom(39,32)

FROM dual;

5/8 19/32

SELECT 5/8 + 19/32

FROM dual;

1.21875 1.21875 == 39/32

Funkce – pozice rodičefunction parent_numer( numer integer, denom integer ) RETURN integer IS

ret_num integer; ret_den integer;BEGIN

if numer = 3 then -- uzel nejvyšší úrovněreturn NULL;

end if;ret_num := (numer-1)/2; -- posun svisle dolů ret_den := denom/2;-- posun vodorovně dopravawhile floor((ret_num-1)/4) = (ret_num-1)/4 loop

ret_num := (ret_num+1)/2;ret_den := ret_den/2;

end loop;RETURN ret_num; -- pro čitatel

END; -- RETURN ret_den; -- pro jmenovatel

Funkce – pořadí mezi sourozenci

function sibling_number( numer integer, denom integer ) RETURN integer IS

ret_num integer; ret_den integer; ret integer;BEGIN

-- uzel nejvyšší úrovně + posun svisle dolů jako v předchozímret := 1; -- inicializace pořadí na 1while floor((ret_num-1)/4) = (ret_num-1)/4 loop -- posun doprava

if ret_num=1 and ret_den=1 then return ret;-- zkoumaný uzel je první syn

end if;ret_num := (ret_num+1)/2; ret_den := ret_den/2;ret := ret+1; -- každá iterace znamená posun o 1

sourozenceend loop;RETURN ret; -- pořadí mezi sourozenci

END;

Vnořené intervaly - příklad2

Uzel 2.1.2 má pozici 27/32 a uzel 2.1 (rodič předchozího) má 7/8

SELECT parent_numer(27,32) || '/' || parent_denom(27,32)

FROM dual;

7/8

SELECT sibling_number(27,32)

FROM dual;

2

Funkce – materializovaná cesta

function path( numer integer, denom integer ) RETURN varchar2 IS BEGIN

if numer is NULL then -- konec rekurzereturn '';

end if;RETURN

-- rekurzivně získá cestu k rodičipath( parent_numer(numer, denom),

parent_denom(numer, denom) ) -- připojí pořadí aktualního uzlu mezi svými sourozenci|| '.' || sibling_number(numer, denom);

END;

SELECT path(15,16) FROM dual;

.2.1.1

Funkce – vzdálenost dvou uzlů

function distance( num1 integer, den1 integer, num2 integer, den2 integer ) RETURN integer IS

BEGINif num1 is NULL then -- signalizuje, ze uzel num2/den2 není

return -999999; -- předkem uzlu num1/den1end if;if num1=num2 and den1=den2 then

return 0; -- došli jsme do num2/den2end if;RETURN1+distance( -- rekurze na rodiče + zvýšení délky cesty

parent_numer(num1, den1),parent_denom(num1, den1), num2, den2 );

END;

SELECT distance(27,32,3,4) FROM dual;2

Funkce – čtení materializované cesty

● Funkce :function path_numer( path varchar2 ) RETURN integerfunction path_denom( path varchar2 ) RETURN integerparsují vstupní řetězec a na každé úrovni pomoci pozice rodiče a pořadí aktuálního uzlu mezi sourozenci vypočítávají pozici aktuálního uzlu

SELECT path_numer('2.1.3') || '/' || path_denom('2.1.3')

FROM dual;

51/64

Test struktury – definice schématu

● předpokládejme, že v tabulce emps máme uložené zaměstnance a jejich pozice získané z materializovaných cest v tabulce vpravo

● create table emps (name varchar2(30),numer integer,denom integer )

● tabulku naplníme sekvencí INSERTů tvaru :INSERT INTO emps VALUES ( 'FORD', path_numer('1.1.2'),path_denom('1.1.2') );

ENAME PATHKING 1JONES 1.1SCOTT 1.1.1ADAMS 1.1.1.1FORD 1.1.2SMITH 1.1.2.1BLAKE 1.2ALLEN 1.2.1WARD 1.2.2CLARK 1.3MILLER 1.3.1

Test struktury – definice schématu

● z tabulky emps a ze zatím definovaných funkcí vytvoříme pohled, nad kterým se bude dobře dotazovat :CREATE OR REPLACE VIEW hierarchy ASSELECT name, numer, denom,

y_numer(numer,denom) numer_left,y_denom(numer,denom) denom_left,x_numer(numer,denom) numer_right,x_denom(numer,denom) denom_right,path (numer,denom) path,distance(numer,denom,3,2) depth

FROM emps;

Test struktury – procházka do hloubky

Výsledek:LPAD('',3*DEPTH) || NAME---------------------------------------KING

CLARKMILLER

BLAKEWARDALLEN

JONESFORD

SMITHSCOTT

ADAMS

Dotaz :

SELECT lpad(' ',3*depth)||name

FROM hierarchy

ORDER BY numer_left/denom_left;

ENAME PATHKING 1JONES 1.1SCOTT 1.1.1ADAMS 1.1.1.1FORD 1.1.2SMITH 1.1.2.1BLAKE 1.2ALLEN 1.2.1WARD 1.2.2CLARK 1.3MILLER 1.3.1

Zdroj :

Test struktury – procházka do hloubky

Výsledek:LPAD('',3*DEPTH) || NAME---------------------------------------KING

JONESSCOTT

ADAMSFORD

SMITHBLAKE

ALLENWARD

CLARKMILLER

Dotaz :

SELECT lpad(' ',3*depth)||name

FROM hierarchy

ORDER BY numer_right / denom_right;

ENAME PATHKING 1JONES 1.1SCOTT 1.1.1ADAMS 1.1.1.1FORD 1.1.2SMITH 1.1.2.1BLAKE 1.2ALLEN 1.2.1WARD 1.2.2CLARK 1.3MILLER 1.3.1

Zdroj :

Test struktury – podřízené

Výsledek:NAME

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

SCOTT

ADAMS

FORD

SMITH

Dotaz :SELECT

h1.name FROM

hierarchy h1, hierarchy h2WHERE

h2.name = 'JONES'AND

distance( h1.numer,

h1.denom,h2.numer,

h2.denom) > 0;

ENAME PATHKING 1JONES 1.1SCOTT 1.1.1ADAMS 1.1.1.1FORD 1.1.2SMITH 1.1.2.1BLAKE 1.2ALLEN 1.2.1WARD 1.2.2CLARK 1.3MILLER 1.3.1

Zdroj :

Test struktury – nadřízené

Výsledek:NAME

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

KING

JONES

Dotaz :SELECT

h2.name FROM

hierarchy h1, hierarchy h2WHERE

h1.name = 'FORD'AND

distance( h1.numer,

h1.denom,h2.numer,

h2.denom) > 0;

ENAME PATHKING 1JONES 1.1SCOTT 1.1.1ADAMS 1.1.1.1FORD 1.1.2SMITH 1.1.2.1BLAKE 1.2ALLEN 1.2.1WARD 1.2.2CLARK 1.3MILLER 1.3.1

Zdroj :

Zdroje● zdrojem pro referát sloužil článek od Vadim Tropashko :

Trees in SQL: Nested Sets and Materialized Pathhttp://www.dbazine.com/oracle/or-articles/tropashko4

● navazující témata :

Nested Intervals with Farey Fractions

http://arxiv.org/html/cs.DB/0401014● newsgroups :

comp.database.theory

comp.database.oracle