Avatar billede hrc Mester
02. juni 2009 - 16:05 Der er 9 kommentarer og
1 løsning

Forslag til et bedre script. Find status på en sag.

Har en status-tabel der er koblet til en given sag.

(
  id int identity(1,1), -- primærnøgle
  sags_id int, -- fremmednøgle til sag
  fra_dato datetime,
  til_dato datetime
)


Sidste record tilknyttet sagen angiver dens status. Hvis "til_dato"'en er udfyldt, er den afsluttet. Er den tom (NULL) er den åben.

Hvordan finder jeg smukkest denne oplysning?

Det jeg har hittet på, er dette:

select fra_dato, til_dato
from sagsdatoer
where id = (select max(ref)
            from sagsdatoer where sags_id = :sags_id)


... hvor ":sags_id" er fremmednøgle til den pågældende sag. Er det virkelig en OK løsning? Der må da være en pænere.

Jeg vil gerne over i er et script, der returnerer de "vigtige" records fra hver af de sager der måtte være tilknyttet.
Avatar billede hrc Mester
02. juni 2009 - 16:20 #1
Er kommet til dette script der tilsyneladende giver mig korrekte resultater.

select id, sags_id, fra_dato, til_dato
from sagsdatoer
where (id in (select max(skd.id)
              from sagsdatoer sd
              join sags s on (s.id = sd.sags_id)
              where (s.borger_id = :borger_id)
              group by s.id))


Spørgsmålet er stadig åbent. Er der en anden tilgang?
Avatar billede arne_v Ekspert
03. juni 2009 - 03:36 #2
prøv:

SELECT TOP 1 *
FROM sagsdatoer join sag s ON s.id = sd.sags_id
WHERE sags_id = s.borger_id = :borger_id
ORDER BY sd.id DESC
Avatar billede hrc Mester
03. juni 2009 - 11:04 #3
Hej Arne. TOP er der naturligvis men er den pænere/mere effektiv? Jeg bruger den aldrig da jeg mistænker den for at være en ydelsesdræber; også i forhold til sub-selects. Nogle gange må den hente en masse data for at kunne sortere den og derefter kun udvælge TOP'pen. Her sorterer den på primærnøglen og det er nok hurtigt.

Grunden til jeg lægger det ud til forum (igen?) er, at det må være noget mange har brug for at gøre. Løsningerne her er ikke gode i en select hvor man eksempelvis vil søge borgere med åbne sager.

Som antydet ovenfor kan jeg ikke se om spørgsmålet allerede er blevet stillet af mig; dvs. bladrer jeg gennem alle mine "posts" så finder jeg det nok, men tidligere kunne man filtrere på spørgsmål oprettet af en selv.

Jeg har også spurgt om man kunne måle ydelsen af en "select" i MSSQL - og det kan man, men jeg kan ikke hitte spørgsmålet.

(Jeg synes det er lidt svært at vænne sig til den ny "Ekspert")
Avatar billede arne_v Ekspert
03. juni 2009 - 16:32 #4
Jeg synes at den er paenere, men det er naturligvis lidt smag og behag.

Jeg ved ikke om den er effektiv. Det kan du teste. Men jeg forventer at den er effektiv, da den ihvertfald teoretisk kan optimeres.

Du kan snage i en query ved foerst at udfoere:

set showplan_all on

og saa proeve query.

(kan vist goeres nemmere i GUI'en)
Avatar billede HenrikSjang Nybegynder
03. juni 2009 - 22:16 #5
Kan du ikke komme med lidt mere info? I din beskrivelse har du både en tabel sagsdatoer og en tabel der hedder sags, men du har ikke beskrevet dem begge. Og hvis du så kan komme med et lille test-data sæt, hvor du så fortæller hvad det forventede output er - så er der lidt større chancer for at få hjælp.

Kører du sql server 2005? For så er jeg næsten 100% sikker på at en cte med brug af row_number() funktionen kan hjælpe med at løse det.
Avatar billede HenrikSjang Nybegynder
03. juni 2009 - 22:23 #6
Mens jeg venter på lidt mere info, så kan jeg da lige komme med et par kodestumper som jeg har lavet ud fra din første beskrivelse: "Sidste record tilknyttet sagen angiver dens status. Hvis "til_dato"'en er udfyldt, er den afsluttet. Er den tom (NULL) er den åben"


with Sager
as
(
select
    ROW_NUMBER() over (partition by sags_id order by id desc) as rn,
    *
from sagsdatoer
)

select * from Sager
where rn = 1 and til_dato is null

Ovenstående vil returnerer den nyeste oprettede row pr. sags_id. Og så bortfiltreres alle de sags_id'er, hvor den nyeste tilknyttede sagsdato ER blevet afsluttet. H Men om det er noget i den stil du er ude efter at få, er jeg altså ikke helt sikker på.
Avatar billede hrc Mester
04. juni 2009 - 11:14 #7
sjang: Der er en sagsdatoer-tabel som hænger på et sags-tabel. Sags-tabellen hænger på en borger-tabel. (sagsdatoer.sags_id -> sags.id, sags.borger_id -> borger.id). Jeg er kun interesseret i den nyeste sagsdatoer-record for hver sag en borger må have.

Umiddelbart lige ud ad landevejen skulle jeg mene.

arne: Jeg sammenlignede vores løsninger med følgende resultat:

Mit (første) script (3 deloperationer):
Estimated IO: 0,02756944
Estimated CPU: 0,0016245
AvgRowSize: 62
TotalSubtreeCost: 0,08886236

Dit script (5 deloperationer):
Estimated IO: 0,03069444
Estimated CPU: 0,00178678
AvgRowSize: 94
TotalSubtreeCost: 0,13184156

.. altså noget tungere at udføre. Jeg fik vist ret mht. TOP. I øvrigt ikke stor forskel om man brugte * eller valgte felterne. Med asterix i selected var AvgRowSize 366 og der kom en deloperation mere på. Resultatet var næsten det samme.
Avatar billede HenrikSjang Nybegynder
04. juni 2009 - 11:45 #8
Jeg prøver lige at strikke noget sammen senere.

Hvis du vil sammenligne reelle queries, så vil jeg foreslå at du fyrer følgende af inden du kører dine queries:

set statistics io on
set statistics time on

Det viser aktuelle antal reads og cpu-tid i message-fanen efter du har eksekveret din kode. Ikke noget med estimated stuff her :)
Avatar billede hrc Mester
18. juni 2009 - 13:06 #9
Arne og Sjang. Jeg lukker nu. Fik ikke strikket et script sammen der var bedre end det jeg havde, men fik nogle rigtig gode tips til at måle på eksperimenterne. Derfor må I dele pointsene.
Avatar billede arne_v Ekspert
18. juni 2009 - 14:12 #10
ok
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