Avatar billede hrc Mester
28. november 2008 - 00:30 Der er 9 kommentarer og
1 løsning

Samle den nyeste detail-record med master-recorden

Givet tabellerne:

Borger
  ID: integer identity(1,1)
  ...

Datoer
  ID: integer identity(1,1)
  Dato: datetime not null

Jeg leder efter den smukkeste måde at hente den nyeste record fra datoer-tabellen og lægge den sammen med borger-tabellen. Skal jeg lave søgninger er det altid den nyeste detail-record jeg skal kigge på

Har leget lidt med dette:

select b.ID
from borger b
join datoer d on (d.ID = (select top 1 ID from datoer where borger_ID = b.ID) and status = :status)

.. men det er ikke smukt og det er garanteret heller ikke hurtigt.

Jeg leder efter den smukkeste/optimale løsning på dette problem for jeg har rodet mig ud i den slags situationer en del gange. Måske findes spørgsmålet allerede besvaret, men jeg ved ikke hvad jeg skal søge efter.
Avatar billede arne_v Ekspert
28. november 2008 - 00:53 #1
Jeg synes der mangler lidt info. Hvordan er PK-FK ? Hvad er borger_id ?

Kan du evt. vise nogle eksempel data ?
Avatar billede arne_v Ekspert
28. november 2008 - 00:54 #2
eksempel data inkl. ønsket output - bare 3 og 5 records eller sådan noget
Avatar billede hrc Mester
28. november 2008 - 03:36 #3
Beklager at der ikke var nok beskrivelse (her i de sene timer kan det blive for spartansk):

To tabeller:

create table borger
(
  ID identity(1,1),
  ..,
  primary key(ID)
)

create table borgerdatoer
(
  ID identity(1,1),
  borger_ID integer foreign key refrerences borger(ID),
  fra_dato datetime,
  til_dato datetime,
  primary key(ID)
)

For hver record i borger vil jeg også gerne have den nyeste record i borgerdatoer der refererer til borgeren, men altid så jeg kun har en record pr. borger.

Hvad output angår ser det sådan her ud:

ref  navn  fra_dato,  til_dato
1    Hulda  10-01-1999
2    Hunke  01-01-2005  01-01-2008

osv. Situationen hvor der ikke er en relaterende record i borgerdatoer er en fejl.
Avatar billede arne_v Ekspert
28. november 2008 - 04:21 #4
mit forslag (utestet):

SELECT b.id,b.navn,bd.fra_dato,bd.til_dato
FROM borger b,borgerdatoer bd,(SELECT borger_id,MAX(fra_dato) AS max_fra_dato FROM borgerdatoer GROUP BY borger_id) x
WHERE b.id=bd.borger_id AND b.id=x.borger_id AND bd.fra_dato=x.max_fra_dato
Avatar billede hrc Mester
28. november 2008 - 11:04 #5
Mit indslag blev skrevet i databasen. Fik ellers en "Beklager men vi opdaterer om natten" besked og troede alt var mistet. Plejer at kopiere til klippebord før jeg submitter, grundet den slags "morsomheder"

Jeg synes ikke det er meget pænere end det jeg selv har brygget sammen (men som jeg altså synes er lidt langsom). Kan ikke bedømme om en "group by" eller en "top" i sub-selecten er bedst.

...
from borger b
join borgerdatoer bd on (bd.ID = (select top 1 ID
                                    from borgerdatoer
                                    where (borger_ID = ba.ID)
                                    order by fra_dato desc)

                    and (til_dato is null or til_dato >= getdate())) // Aktive
  .. eller
                    and til_dato is not null) // Henlagte
Avatar billede arne_v Ekspert
28. november 2008 - 17:34 #6
Grunden til at jeg foretrækker join fremfor en select top 1 er at det er nemt
for optimizeren kun at udføre query x en enkelt gang.

Men prøv og test hastighed med større datamængder.
Avatar billede hrc Mester
29. november 2008 - 20:16 #7
Tak Arne.

Endnu er hastigheden en ubetydelig faktor, men når tiden går kan det blive aktuelt at optimere. Måske skal jeg bare registrere den aktuelle records ID i borger-tabellen? Så var det en singleton select... Har alligevel tænkt mig at proppe gemme operationen ned i en SP.

Engang du får tid skal du bare smide et svar...
Avatar billede arne_v Ekspert
29. november 2008 - 21:11 #8
Du kan vel lave nogle kunstige data og teste på.

Det var også en måde at gøre det på. Bedre performance men også en form for redundante
data.

Og svar.
Avatar billede hrc Mester
29. november 2008 - 21:31 #9
Jeg lærte i skolen, at når databasen endte i 3 normalform eller deromkring, burde man overveje at genindføre redundans for bedre ydelse. Det var ikke meget jeg fangede dengang (oveni kærstesorger, nær mikrobankerot og generel kedsomhed), men lidt hænger da ved.
Avatar billede arne_v Ekspert
29. november 2008 - 22:51 #10
Det sker at det er nødvendigt. Men det er ret sjældent til generelle databaser. Ofte
vil fornuftig brug af indexes få det til at fungere. Hvis man har brug for hårdhændede
metoder, så er et materialized view ofte bedre end en denormaliseret tabelstruktur. Men
det sker at det bliver brugt.
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