← Back to team overview

sslug-teknik team mailing list archive

SQL - select intersect except

 

Hej.

Jeg har nu siddet og bakset lidt med en database, og selv om jeg har
løst mit umiddelbare problem, må der være smartere måde at gøre tingene
på.


Løsningen på problemet er:

select i from t where v=1
  intersect
    select i from t where v=2
  except
    select i from t where v not in (1, 2);

Dette finder den værdi "i" i tabellen "t" som har nøjagtig "v"=1 og "v"=2
tilknyttet.


Er der nogen der kender en smartere måde at gøre ovenstående på?

Det skal lige siges, at der en gang imellem arbejdes man med op til 3
intersects og en except med 4 "in" værdier. Tabellen bliver næppe større
end et par tusinde rækker.


Forklaring:

Jeg har en tabel i en postgres database der er defineret som

create table t (
	i integer,
	v integer,
);
create unique index iv_idx on t (i, v);


Denne tabel kan f.eks. indeholde værdierne:

| i | v |
---------
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |
| 5 | 1 |
| 5 | 2 |
| 6 | 1 |
| 6 | 2 |
| 6 | 3 |
| 7 | 1 |
| 7 | 2 |
| 7 | 4 |
---------


Formålet:

Jeg har en lille bogdatabase, hvor en forfatter er opbygget af et antal
personer. Det kan jo hænde at flere har samarbejdet om en bog. Problemet
har jeg så klaret ved at lave en persontabel og en bogtabel. Bogens
forfatter er så en indeks-værdi der peger på en mellemtabel, hvor alle
personer er sat sammen med 0 eller flere andre for at danne en forfatter.
På den måde kan en person være med i flere "forfatter" enheder. Disse
enheder kan så bruges til at angive bogens "forfatter".


-------------   -------------    -------------
|  Bog      |   | Forfatter |    | Person    |
-------------   -------------    -------------
| forf_idx  |---| forf_idx  |  |-| pers_idx  |
| bog info  |   | pers_idx  |--- | pers info |
-------------   -------------    -------------

Når jeg nu ønsker at indsætte en ny bog angiver jeg blot forfatterenheden,
hvorefter jeg undersøger om forfatterenheden eksisterer. Det er eksistensen
af forfatter-enheden jeg er ude efter.

Hvis jeg i ovenstående eksempel f.eks. laver en ny forfatterenhed
bestående af personerne med indeks 2 og 4, vil jeg, når jeg tester om
forfatteren findes få 0 rækker tilbage, og skal derfor danne en ny
forfatter hvor (i,v) = (8,2), (i,v) = (8,4).

Man bør altså altid få 0 eller 1 række tilbage på et spørgsmål.


Det var såmænd i al sin simpelhed problematikken.


Med venlig hilsen
Bjørn Bille Højte
bjoern@xxxxxxxxxxxxx





Follow ups