stromy a hierarchické struktury v sql
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 PresentationTRANSCRIPT
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