Avatar billede tto78 Nybegynder
01. februar 2004 - 15:22 Der er 9 kommentarer

Formulering af en effektiv SQL sætning

Jeg søger hjælp til at foretage et opslag på mest optimale måde i min Postgres 7.4.1 db (under debian). Jeg har selv lavet en query som via en sub-query pr. resultat finder det jeg har brug for, men da der ofte kan være 500-1500 resultater ønsker jeg en query der har et fast antal opslag, uanset antallet af resultater.

Jeg har to tabeller: item og retailprice

Hvert item kan have 1..m retailprice records. Hver retailprice har et 1..1 obligatorisk forhold til item. Årsagen til at et item kan have flere retailprice's er at hver retailprice har en startdato (og historikken ang. tidligere priser ønskes bevaret). Den query jeg ønsker skal dog finde et eller flere items med deres respektive AKTUELLE retailprice. Dvs. den retailprice med den højeste startdato som ikke er > now().

Tabellerne ser således ud (kun relevant info medtaget):

ITEM:
itemno int4 PRIMARY KEY
... en masse felter

RETAILPRICE:
retailpriceno int4 PRIMARY KEY
retailprice float4
startdate timestamp
... et par andre felter

Mit problem er at jeg skal lave en join mellem item og retailprice med nogle kriterier from giver mig et 1..1 forhold i hver resulterende række. Jeg er nået hertil:

SELECT i.*, r.* FROM item i, retailprice r where i.itemno=r.itemno AND r.startdate < now;

Jeg håber på et svar som enten:

Beskriver den query som løser problemet i et fastantal queries uanset antal resulterende rækker

eller ...

Beskriver et alternativt table design og en tilhørende query som kan løse problemet.

pft.
Avatar billede lap Nybegynder
01. februar 2004 - 15:33 #1
Jeg er ikke sikker på din tekstbeskrivelse af problemet, men er det du ønsker noget lignende:

select i.*, r.* FROM item i, retailprice r where i.itemno=r.itemno AND r.startdate = (select max(startdate) from retailprice r2 where r2.itemno=i.itemno group by r2.itemno)
Avatar billede lap Nybegynder
01. februar 2004 - 15:35 #2
Det burde give dig en record per item/retailprice, hvor den altid vælger den retailprice-record, hvor startdate er størst (=nyest).
Avatar billede tto78 Nybegynder
01. februar 2004 - 15:36 #3
Giver det ikke netop et opslag pr. resultat for at finde max(startdate) ?
Avatar billede lap Nybegynder
01. februar 2004 - 15:39 #4
jo, men i sql er det faktisk den eneste metode at gøre dette på. Performance mæssigt bør det ikke være noget problem.

Det er muligt, at det var måden du allerede gjorde det på, men din eksisterende kode kunne jo, ha afsløret dette.

En metode til optimering kunne være at udvide retailprice tabellen med en slutdato (som selvfølgelig er implicit) - så kunne du sige "where enddate is null" - og kunne laves med et rent join.

Normalmetoden for at lave ovenstående i flad sql er ovenstående metode.
Avatar billede lap Nybegynder
01. februar 2004 - 15:42 #5
forresten kan et index på itemno, startdate optimere dette (hvis ellers PostgreSQL opfører sig som oracle rulebased)
Avatar billede kimhanse Nybegynder
02. februar 2004 - 18:29 #6
Brug noget ikke-standard-SQL som PostgreSQL kan:

SELECT DESTINCT ON (itenno, startdate) *
FROM item JOIN retailprice USING (itemno)
WHERE startdate <= NOW()
ORDER BY itemno DESC, startdate DESC;
Avatar billede kimhanse Nybegynder
02. februar 2004 - 18:30 #7
Hov, det var ment som et svar.

Det kan forresten betale sig at have et index på (itemno,startdate) så kan det benyttes ved sorteringen. Det er også derfor jeg har sat den til at sortere omvendt på itemno.
Avatar billede tto78 Nybegynder
02. februar 2004 - 19:57 #8
Beklager, men den nævnte query giver IKKE en række pr. item med aktuelle pris.
Avatar billede kimhanse Nybegynder
02. februar 2004 - 20:11 #9
Så er jeg ikke sikker på at jeg har forstået din beskrivelse af databasen rigtigt. Hvilket resultat giver den query jeg har beskrevet?
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