Avatar billede erve Nybegynder
27. oktober 2001 - 10:30 Der er 17 kommentarer og
2 løsninger

select sidst ændrede række

Givet en tabel T med bl.a felterne id,Xid,datoopret og datoret, hvor id=teknisk id,xid er en fremmednøgle,datoopret er sysdate for det INSERT-statement der skabte rækken, men datoret er sysdate for det UPDATE-statement der evt sidst har ændret rækken.
Jeg vil gerne selecte de sidst berørte rækker pr Xid, altså den række pr Xid, som er insert\'ed eller update\'d sidst.

Det er en eksisterende database, hvor der ikke kan tilføjes nye felter eller andet sjovt?
Mvh Erik
Avatar billede Slettet bruger
27. oktober 2001 - 12:51 #1
Det simpleste er vel

  select XId
  from T
  where greatest(datoopret, datoret) = (
    select max(greatest(datoopret, datoret))
    from T
  )

Dette forhindrer formodentlig at man kan lave
intelligent brug af indekser.

Hvis man vil have ændrede rækker indenfor de sidste dage kunne man skrive:

  select Xid
  from T
  where greatest(datoopret, datoret) = (
    select max(greatest(datoopret, datoret))
    from T
    where greatest(datoopret, datoret) > (SYSDATE - :1)
  )

Hvor \':1\' er \'antal dage\'
Avatar billede Slettet bruger
27. oktober 2001 - 12:56 #2
Ups! Det sidste virker naturligvis ikke, det skulle have været:

\"Hvis man vil have ændrede rækker indenfor de sidste dage kunne man skrive:

  select Xid
  from T
  where datoopret > (SYSDATE - :1)
  or datoret > (SYSDATE - :1)

Hvor \':1\' er \'antal dage\'
Avatar billede Slettet bruger
27. oktober 2001 - 13:04 #3
Hvis man har indekser på datoret og datoopret kan man hurtigere få Xid på den sidst ændrede række ved at skrive:

select *
from (
    select *
    from (
        select Xid, datoopret dato
        from T
        where datoopret = (select max(datoopret) from T)
    union all
        select Xid, datoret dato
        from T
        where datoret = (select max(datoret) from T)
    )
    order by dato
) where rownum < 2

Avatar billede teepee Nybegynder
27. oktober 2001 - 13:05 #4
Hvorfor ikke blot:

select *
from t t1
where datoret = (
  select max(t2.datoret)
    from t t2
  group by xid
  having t2.xid = t1.xid)
Avatar billede Slettet bruger
27. oktober 2001 - 13:05 #5
Se SQL Reference manual om operatorer mv. på fx. http://technet.oracle.com/doc/server.804/a58225/ch3all.htm
Avatar billede Slettet bruger
27. oktober 2001 - 13:07 #6
teepee --> Det kan være, du har ret. Jeg har nok misforstået, hvad man mener med \'fremmednøgle\'
Avatar billede erve Nybegynder
27. oktober 2001 - 13:21 #7
Tak Joern_h
Dit første eksempel med greatest virker næsten. Det tager ikke de rækker med hvor kun datoopret er udfyldt og datoret er null, altså de rækker som aldrig er blevet update\'et. Kan du få dem med er point\'ene dine :o)
Mvh ERik
Avatar billede erve Nybegynder
27. oktober 2001 - 13:22 #8
Hej teepee
Tak for svaret, men dit eksempel select\'er kun på datopret, og jeg skal bruge de rækker pr xid hvor enten datoret eller datoopret er størst
Avatar billede teepee Nybegynder
27. oktober 2001 - 13:28 #9
det letteste vil være også at smide sysdate i datoret ved oprettelse
Avatar billede erve Nybegynder
27. oktober 2001 - 13:30 #10
teepee:
Enig, men det er som en sagt en base der er i produktion, som helst ikke må pilles ved.
Avatar billede teepee Nybegynder
27. oktober 2001 - 13:32 #11
jeg tænker lige over den, for den er ikke helt let så...
Avatar billede Slettet bruger
27. oktober 2001 - 13:48 #12
Kan pointene blive mine?

Måske kan man bruge en

greatest (datoopret, nvl(datoret, datoopret))
Avatar billede erve Nybegynder
27. oktober 2001 - 14:40 #13
Æw - god ide, men nu kommer alle rækker ud....

Mener du:

select XId
  from T
  where greatest (datoopret, nvl(datoret, datoopret))  = (
    select max(greatest (datoopret, nvl(datoret, datoopret)) )
    from T
  )
Avatar billede Slettet bruger
27. oktober 2001 - 16:39 #14
Det lyder mærkeligt, at alle rækker nu kommer væltende?

Er datoopret altid udfyldt? Hvis ikke, kan der måske være problemer i at køre greatest-operatoren på, fordi den så vil konvertere til varchar2.
Avatar billede andy2003 Nybegynder
28. oktober 2001 - 14:25 #15
Hvad med :

select Xid, greatest(max(datoret), max(datoopret))
from T
group by xid
Avatar billede teepee Nybegynder
29. oktober 2001 - 08:35 #16
Nu er jeg ikke lige i nærheden af en database, så dette er ikke afprøvet:

select *
from t t1
where nvl(datoret, datoopret) = (
  select max(nvl(t2.datoret, t2.datoopret))
    from t t2
  group by xid
  having t2.xid = t1.xid)
Avatar billede erve Nybegynder
29. oktober 2001 - 09:40 #17
teeppe: giver sqlfejl not a group expression
andy2003: tæt på, men returnerer forkert maxdato hvor datoret is null
Avatar billede teepee Nybegynder
29. oktober 2001 - 10:09 #18
Jeg tænkte det nok, men enten kan du oprette et view, det nvl\'er datoopret ind i datoret, hvor denne er null, eller også kan du lave en subselect som laver en slags runtime view. Så erstat T med viewet select id, xid, datoopret, nvl(datoret, datoopret) datoret from T. Så du\'r min første select
Avatar billede erve Nybegynder
05. november 2001 - 19:21 #19
Hej
Tak for hjælpen. Jeg kunne bruge noget af jer begge to\'s indlæg, så I får lov at dele, OK?
Mvh ERik
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