14. marts 2001 - 09:48Der er
4 kommentarer og 1 løsning
Inner/outer join på tre tabeller
Jeg har tre tabeller, som hedder henholdsvis: bruger (id samt brugerdata - navn, rolle, initialer) gruppe (id samt gruppedata - navn, id på overenhed) brugergrupperel (gruppeid, brugerid og rettighed)
Jeg skal lave en søgning på tabellerne (i en stored procedure), og jeg skal søge efter brugere som overholder bestemte data (data kan gå på både brugeren (f.eks. navn), gruppe (f.ek.s navn) eller relationen (rettigheder). Disse brugere skal listes sammen med deres eventuelle gruppedata samt rettighed. Dvs en bruger skal listes én gang pr gruppe og brugere som ikke er med i en gruppe skal listes én gang.
Når jeg laver denne join, får jeg enten en fejlmeddelelse om at \"Query contains an illegal outer-join request.\" eller også får jeg listet en liste af alle brugere og deres forhold til alle brugere og deres forhold til alle grupper.
Jeg synes det er svært, så den giver 60 points. 100 points for fuld query. Hastighed af querien er vigtig.
I lang tid har samarbejdsbranchen fokuseret på at forbedre enhedsfunktioner – bedre kameraer, klarere lyd og smartere software. Men den virkelige forvandling handler ikke om funktioner.
Jeg har ikke problemer med indexes, hvis de ikke allerede er der, så vil jeg få dem på plads når jeg ser hvilke krav udtrækket stiller.
Følgende er mine forkerte løsningsforslag. Den giver følgende resultat: Msg 301, Level 16, State 1 Query contains an illegal outer-join request.
(Jeg er ikke helt klar over om den i øvrigt ville gøre som jeg ønsker ;-)
CREATE PROCEDURE DIS_Users_HentListe -- {Purpose: Hent en liste over brugere} ( @Trace int = 0, @Id int=NULL, @Initialer varchar(20) = NULL, @LC int=NULL, @Gruppe int=NULL, @Rolle varchar(50)=NULL, @Rettighed int=NULL, @ListOnlyOnce tinyint=0, -- should the query be distinct? @ReturnCode int=0 output ) as begin -- Preconditions -- Hvis Gruppe er angivet, så er LC også angivet if (@LC IS NULL AND @Gruppe IS NOT NULL) begin select @ReturnCode = 0 return end
Select @ReturnCode = 1
select * from bruger b, brugergrupperel bg, gruppe g where b.id *= bg.brugerid and g.id =* bg.gruppeid and (g.id = @gruppe OR @gruppe IS NULL) and (g.lcid = @lc or @lc is NULL) and (b.id = @id OR @ID IS NULL) and (b.initialer like \"%\" + @Initialer + \"%\" OR @Initialer IS NULL) and (b.rolle = @rolle OR @Rolle IS NULL) and (bg.rettighed = @rettighed or @rettighed IS NULL) select @ReturnCode = 1 end
Overvej at bruge UNION til at få de brugere med, som ikke er med i en gruppe - det vil gøre den anden del af querien ganske mere overskuelig - noget i stil med:
select * from bruger b join brugergrupperel bg on bg.brugerid = b.id join gruppe g on g.id = bg.gruppeid where (diverse betingelser)
UNION select *, -1 AS Permission from bruger b2 where (not exists (select * from brugergrupperel bg2 where bg2.brugerid = b2.id))
Jeg har ikke testet det, men tillader mig at lade det være et svar alligevel.
Vær opmærksom på at de to selects skal returnere samme antal kolonner med samme navne, derfor - as Permission - på samme måde med de andre kolonner.
Jeg havde håbet på at kunne undgå union. Det er vel ikke så sjældent at man skal joine tre tabeller hvoraf den ene er en relationstabel.
Tak for hjælpen.
Synes godt om
Ny brugerNybegynder
Din løsning...
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.