Avatar billede f2f4 Novice
29. marts 2004 - 09:41 Der 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!

Mvh. Morten
Avatar billede simonvalter Praktikant
29. marts 2004 - 09:51 #1
med pl/sql har du muligheden for at lave if-then-else
http://www.geocities.com/cliktoprogram/plsql/ifstatements.html
og det ser ud som om du bruger oracle, så det skulle være muligt.

og nej jeg tror ikke jeg kan overskue det uden at kunne sidde og teste på databasen selv desværre ;/
Avatar billede f2f4 Novice
29. marts 2004 - 09:57 #2
Ja det er rigtigt at jeg bruger Oracle - tak for link jeg ser på det
Avatar billede trer Nybegynder
29. marts 2004 - 10:02 #3
Afhængigt af Oracle version skal du enten bruge DECODE() eller CASE statements. Så kan du få et "IF" statement direkte i din query.
Avatar billede f2f4 Novice
29. marts 2004 - 10:04 #4
og dog ...

IF count(*) from stillingskategori > 2 then
*
ORA-00900: invalid SQL statement
Avatar billede f2f4 Novice
29. marts 2004 - 10:06 #5
Det er en gammel Oracle: 7.3.4.0.1
Avatar billede trer Nybegynder
29. marts 2004 - 10:12 #6
Som nævnt ovenfor: Check syntaksen på DECODE() - det er din eneste mulighed for at få det "inline" i din SQL.
Avatar billede f2f4 Novice
31. marts 2004 - 09:25 #7
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
Avatar billede trer Nybegynder
31. marts 2004 - 09:34 #8
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).
Avatar billede f2f4 Novice
15. april 2004 - 11:07 #9
tak!
Avatar billede Ny bruger Nybegynder

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.

Loading billede Opret Preview
Kategori
Computerworld tilbyder specialiserede kurser i database-management

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester