29. marts 2004 - 09:41Der er
8 kommentarer og 1 løsning
Vedr. 'avanceret' SQL udtræk
Avanceret select sætning
Jeg ønsker at lave en 'sammenkobling' af nedenstående 2 select sætning!!? De er lidt lange men hvis bare jeg kan få lidt hjælp på hvordan jeg sql mæssigt løser et 'if-then-else' problem vil jeg blive glad!
Data forklaring: Medlems og betalings data. Der betales flere gange om året hvilket styres af et løbenr (LobeNr).
1. SQL: 1. selectsætningen gør følgende: Finder de medlemmer som har over 5000 kr. forskeld mellem deres sidste betaling fra år 2003 og sidste betaling for 2004
select CprNr, navn, a.belob, b.belob from betaling a, betaling b, medlem where a.Aar=2004 and b.Aar=2003 and a.id = b.id and //medlemmer der har betalt i 2003 og 2004 a.LobeNr = (select max(LobeNr) from betaling where Aar=2004 and betaling.id = a.id) and //sidste løbenr for medlemsbetaling i 2004 b.LobeNr = (select max(LobeNr) from betaling where Aar=2003 and betaling.id = b.id) and //sidste løbenr for medlemsbetaling i 2003 ABS(a.belob - b.belob) > 5000 and //Oracle kommande - belobsforskel > 5000 a.id=medlem.id
2. SQL: 2. selectsætningen gør følgende: Finder de medlemmer som har over 5000 kr. forskeld mellem deres sidste betaling (for år 2004) registreret i tabel betalinga og deres sidste betaling (for år 2002) registreret i tabel betalingb select CprNr, navn, beloba, belobb from betaling, betalingb, medlem where betaling.Aar=2004 and betalingb.Aar=2002 and betaling.id = betalingb.id and betaling.LobeNr = (select max(LobeNr) where Aar=2004 from betaling) and betalingb.LobeNr = (select max(LobeNr) where Aar=2002 from betalingb) and ABS(betaling.belob - betalingb.belob) > 5000 betaling.id=medlem.id
Jeg ønsker en samlet SQL hvor jeg får medlemmer med over 5000 kr. i forskelde på årets (2004) sidste betaling. Hvis medlemmet forefindes i tabellen betalingb, skal 2004 beløbet (fra betaling) sammenlignes med 2002 beløbet fra betalingb, hvis ikke medlemmet forefindes i tabellen betalingb, skal 2004 beløbet (fra betaling) sammenlignes med 2003 beløbet fra betaling (samme tabel).
Er der mon nogle der kan overskue dette og hjælpe mig på vej? (Det jeg ikke helt kan gennemskue er hvordan en 'if-then-else' ting kan laves sql mæssigt!). I så fald mange tak!
Jeg må indrømme at det ikke er lykkedes mig ved brug af DECODE (for mig at se skal der testes på '=' og ikke '>' eller '<', men det kan jo være jeg ikke har fundet nok omkring dette). Men jeg tror følgende sql løser mit problem!
select s.CprNr, s.Navn, a.aar, a.belob, b.aar, b.belob, c.aar, c.belob from betaling a, betaling b, betalingb c, medlem where a.aar=2004 and a.belob<>0 and (b.aar=2003 or b.aar=null) and (c.aar=2002 or c.aar=null) and a.id=medlem.id and a.LobeNr=(select Max(LobeNr) from betaling where aar=2004 and betaling.id=a.id) and b.LobeNr=(select Max(LobeNr) from betaling where aar=2003 and betaling.id=b.id) and c.LobeNr=(select Max(LobeNr) from betalingb where betalingb.id=c.id) and ( ( (c.belob>0) and (ABS(a.belob-c.belob > 5000) ) or ( (c.belob=0) and (ABS(a.belob-b.belob) > 5000)) ) and a.id=b.id and order by CprNr
Et lille tip og du ved det sikkert allerede, men med rulebased optimizer (jeg mener ikke der er cost based i Oracle 7) så er det op til dig at sikre den bedst mulige query plan.
Generelt skal man sikre sig, at de betingelser der skærer flest rækker fra står først og i samme rækkefølge som de er understøttet i indeks. Og optimizeren tager kun 1 indeks i betragtning når den laver query plan - så der kan måske også hentes lidt ved at lave et sammensat indeks henover kolonnerne aar, belob, id og lobenr.
Og så vidt jeg husker skal du manuelt flushe cachen før den vælger at udnytte et nyt indeks, ellers bruger den den cachede query plan selvom du lægger nye indeks på (i hvertfald til du vender instansen næste gang).
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.