Welcome to Sign in | Help
in Search

Relationare

Last post 07-02-2007, 10:54 AM by Cypress. 5 replies.
Sort Posts: Previous Next
  •  06-30-2007, 5:17 PM 2178

    Relationare

    Acum invat SQL. deci va rog sa nu ma iertati daca problemele mele par banale...

     

    Cum ati concepe tabelele care reprezinta lista de angajati ai unei organizatii, incluzand relatia ierarhica dintre fiecare angajat si superiorul sau? 

  •  06-30-2007, 7:38 PM 2179 in reply to 2178

    Re: Relationare

    de ex ai tabela angajati cu urmatoarea structura:

    idangajat-pk

    idmanager-fk

    apoi coloane cu celelate angajat

    Important ca tabela asta idmanager-este un self foreign key adik este un foreignkey care bate catre un pk din acceasi tabela cu ea.

    Pentru afisarea ierarhica a inregistrarilori din tabela asta poti folosi CTE-uri recursive asta dak ai sql2005

     

     


    Secolul XXI ori va fi religios ori nu va fi deloc
  •  06-30-2007, 8:13 PM 2180 in reply to 2179

    Re: Relationare

    Daca lucrezi pe SQL 2005, ai in baza de date "didactica" AdventureWorks un exemplu - vezi schema "HumanResources".

    Vezi si diagrama bazei la http://www.microsoft.com/downloads/details.aspx?familyid=0f6e0bcf-a1b5-4760-8d79-67970f93d5ff&displaylang=en.

    Pe SQL 2000, tin minte ca exista ceva destul de simplu in baza "Northwind"... 

  •  07-01-2007, 12:22 PM 2182 in reply to 2180

    Re: Relationare

    Nu-mi iasa deloc pasentzele cu enuntul asta....
  •  07-01-2007, 9:08 PM 2183 in reply to 2178

    Re: Relationare

    Există mai multe moduri de a stoca un arbore într-o tabelă. Cel mai uzual mod este numit „Adjacency list” şi un exemplu ar arăta astfel: 

     

    CREATE TABLE Salariati (
         
    ID int PRIMARY KEY,
         
    Nume nvarchar(20) NOT NULL,
         
    Prenume nvarchar(30) NOT NULL,
         
    ID_Sef int NULL REFERENCES Salariati (ID)
    )

    INSERT INTO Salariati VALUES (1, 'Popescu', 'Ion', NULL)
    INSERT
    INTO Salariati VALUES (2, 'Ionescu', 'George', 1)
    INSERT
    INTO Salariati VALUES (3, 'Vasilescu', 'Marian', 1)
    INSERT
    INTO Salariati VALUES (4, 'Vasilescu', 'Mihai', 3)
    INSERT
    INTO Salariati VALUES (5, 'Popescu', 'Marian', 3)
    INSERT
    INTO Salariati VALUES (6, 'Popescu', 'Vasile', 4)
     

    Dacă vrem să aflăm lista tutor subordonaţilor (direcţi sau indirecţi) ai unei anumite persoane, putem folosi o funcţie de genul următor:

     

    CREATE FUNCTION Subordonati(@ID int)
    RETURNS @Rezultat TABLE (
         
    ID int PRIMARY KEY,
         
    Nume nvarchar(20) NOT NULL,
         
    Prenume nvarchar(30) NOT NULL
    )
    AS BEGIN
         
    INSERT INTO @Rezultat
          SELECT ID, Nume, Prenume FROM Salariati
          WHERE ID_Sef=@ID 

          WHILE @@ROWCOUNT<>0 BEGIN
               
    INSERT INTO @Rezultat
               
    SELECT ID, Nume, Prenume FROM Salariati
                WHERE ID_Sef IN (SELECT ID FROM @Rezultat)
               
    AND ID NOT IN (SELECT ID FROM @Rezultat)
         
    END 

          RETURN
    END

    GO

    SELECT * FROM Subordonati(3) 

     

    Un alt model de a stoca un arbore este cel numit „Materialized paths”, care ar fi ceva de genul următor: 

     

    CREATE TABLE Salariati (
         
    ID int PRIMARY KEY,
         
    Nume nvarchar(20) NOT NULL,
         
    Prenume nvarchar(30) NOT NULL,
         
    Path varchar(10)
    ) 

    INSERT INTO Salariati VALUES (1, 'Popescu', 'Ion', 'A')
    INSERT
    INTO Salariati VALUES (2, 'Ionescu', 'George', 'AA')
    INSERT
    INTO Salariati VALUES (3, 'Vasilescu', 'Marian', 'AB')
    INSERT
    INTO Salariati VALUES (4, 'Vasilescu', 'Mihai', 'ABA')
    INSERT
    INTO Salariati VALUES (5, 'Popescu', 'Marian', 'ABA')
    INSERT
    INTO Salariati VALUES (6, 'Popescu', 'Vasile', 'ABAA')

     

    În acest caz, funcţia care returnează toţi subordonaţii unei persoane poate fi implementată mult mai uşor (şi mai eficient), printr-o căutare cu operatorul LIKE:

     

    CREATE FUNCTION Subordonati(@ID int)
    RETURNS TABLE AS RETURN
    SELECT ID, Nume, Prenume FROM Salariati
    WHERE
    Path LIKE (
         
    SELECT Path FROM Salariati
          WHERE ID=@ID
    )+
    '_%' 

    GO

    SELECT * FROM Subordonati(3) 

     

    Dezavantajul acestei metode este că limitează adâncimea şi lăţimea arborelui (de exemplu, în acest caz am limitat la maximum 10 nivele, iar fiecare persoană poate avea maximum 26 de subordonaţi direcţi, pt că am folosit câte o literă pentru codificarea fiecărui nivel; desigur, codificarea poate fi modificată să permită de exemplu câte două litere pentru fiecare nivel şi un număr mult mai mare de nivele, dar trebuie totuşi să se stabilească de la început nişte limite maxime).

     

    Al treilea model este cel numit „Nested sets” şi a fost popularizat destul de mult de către Joe Celko. Acest model presupune „proiecţia” arborelui pe o axă a numerelor întregi şi stocarea două valori pentru fiecare nod, de exemplu: 

     

    /                       Popescu Ion                                           \
       / Ionescu George \   / Vasilescu Marian                                \
                               / Vasilescu Mihai      \  / Popescu Marian \
                                  / Popescu Vasile \

    1  2                3   4  5  6                7  8  9                10  11  12


    CREATE
    TABLE Salariati (
         
    ID int PRIMARY KEY,
         
    Nume nvarchar(20) NOT NULL,
         
    Prenume nvarchar(30) NOT NULL,
         
    L int NOT NULL,
         
    R int NOT NULL,
         
    CHECK (L<R)
    )

    INSERT INTO Salariati VALUES (1, 'Popescu', 'Ion', 1, 12)
    INSERT
    INTO Salariati VALUES (2, 'Ionescu', 'George', 2, 3)
    INSERT
    INTO Salariati VALUES (3, 'Vasilescu', 'Marian', 4, 11)
    INSERT
    INTO Salariati VALUES (4, 'Vasilescu', 'Mihai', 5, 8)
    INSERT
    INTO Salariati VALUES (5, 'Popescu', 'Marian', 9, 10)
    INSERT
    INTO Salariati VALUES (6, 'Popescu', 'Vasile', 6, 7)
     

    Funcţia care returnează subordonaţii unei persoane arată astfel: 

     

    CREATE FUNCTION Subordonati(@ID int)
    RETURNS TABLE AS RETURN
    SELECT
    A.ID, A.Nume, A.Prenume
    FROM
    Salariati A, Salariati B
    WHERE
    B.ID=@ID
    AND
    A.L>B.L AND A.R<B.R 

     

    De asemenea, căutarea tuturor subordonaţilor se poate face mai eficient decât în primul model, însă adăugarea de noduri noi este mult mai dificilă, deoarece trebuie renumerotate toate valorile (pentru a asigura faptul că sunt întregi şi consecutive).

     

    Un model asemănător cu cel precedent, este „Nested intervals”, care permite şi valori fracţionare, uşurând astfel adăugarea de noi noduri.

     

    Pentru mai multe informaţii, vezi următoarele articole:
    http://www.dbazine.com/oracle/or-articles/tropashko4
    http://www.intelligententerprise.com/001020/celko.jhtml?_requestid=1266295

    Răzvan

  •  07-02-2007, 10:54 AM 2184 in reply to 2183

    Re: Relationare

    Fara cuvinte...multumesc mult....

     

    Oferi si meditatii?Big Smile

     

View as RSS news feed in XML
Powered by Community Server (Commercial Edition), by Telligent Systems