Avatar billede hrc Mester
19. juni 2006 - 09:55 Der er 9 kommentarer og
1 løsning

Hent fra dato - 1 og frem

Jeg har en tabel med bl.a. et dato-felt. Fra en given dato vil jeg gerne have alle de records hvor:

1. datoen er null
2. den dato der er mindre end og ligger tættest på den givne dato
3. alle datoer der ligger efter den givne dato:

                given dato
(+) ----------------+---------------------
    (-) o-----------+---------------------
          (+) 0-----+---------------------
                      (+) o---------------
                            (+) o--------

Resultat: 4 records

Ikke det helt idelle resultat da recorden med null i dato-feltet kommer med selvom der faktisk er en record med med dato ældre end den givne. Den burde overstyre. Jeg kan eventuelt sortere den fra efterfølgende. Det bedste resultat er dette:

                given dato
(-) ----------------+---------------------
    (-) o-----------+---------------------
          (+) 0-----+---------------------
                      (+) o---------------
                            (+) o--------

Resultat: 3 records

Databasen er Interbase/Firebird, men skal helst være platformuafhængig da det snart skal porteres til mssql. Da der tilføjes mange records til tabellen er det ikke praktisk at hente alle ind og lave en sortering bagefter. Det vil snart blive sløvt.

Er der en sql-haj der kan brygge sådan en query sammen?

Alternativet er en stored-procedure, ikke?
Avatar billede beef12 Nybegynder
19. juni 2006 - 23:33 #1
Jeg håber jeg har forstået spm korrekt. Jeg har lavet en forespørgsel som jeg mener vil kunne understøtte de tre kriterier du opstiller (ikke testet):

varDato er den 'givne' dato du omtaler:

select
*
from
dinTabel
where
dato = NULL
OR dato < varDato
union all
select
top 1 *
from
dinTabel
order by
datediff(day, dato, varDato)


Håber det kan hjælpe dig videre.
Avatar billede beef12 Nybegynder
19. juni 2006 - 23:37 #2
Hov der var lige noget jeg havde overset, nemlig at i 2) skriver at datoen skal være mindre end og tættest på den givne dato:


select
*
from
dinTabel
where
dato = NULL
OR dato > varDato
union all
select
top 1 *
from
dinTabel
where
dato < varDato
order by
datediff(day, dato, varDato)
Avatar billede hrc Mester
20. juni 2006 - 08:41 #3
Desværre er "top" ikke med i de databaser jeg bruger. Det havde jeg prøvet, men glemt at nævne. Funktionen DateDiff forstår jeg ikke helt - hvad er grunden til den?

I øvrigt kan jeg ikke hitte ud af at få en "order by" smækket på. Resultatet blev derfor følgende:

select * from ydtaksttype
  where (dato is null or dato > '06-15-2006') and debid=8
  union
    select * from ydtaksttype
    where dato < '06-15-2006' and debid=8

Så vidt jeg kan se skal det ikke være en "union all" da de to selects' kan levere overlappende recordset. Det havde været rart med en "top".
Avatar billede hrc Mester
20. juni 2006 - 08:51 #4
I øvrigt skulle tjekket for null have været omvendt. Hvis en record havde en null-dato men, at der fandtes dato-records ældre end den givne dato, skulle scriptet vælge disse. Det falder på, at man tilsyneladende ikke kan sortere sit sub-resultatsæt på dato og bruge "top"'en sammen med det.

select * from ydtaksttype
  where dato > '06-15-2006' and debid=8
  union
    select * from ydtaksttype
    where (dato is null or dato < '06-15-2006') and debid=8
Avatar billede beef12 Nybegynder
20. juni 2006 - 18:40 #5
jamen skulle det ikke snart porteres til MSSQL :-)

Datediff anvender jeg til at finde ud af forskellen mellem to datoer. Jeg laver en order by på denne og snupper den første, idet denne ligger tættest på den givne dato.

Jeg vender tilbage lidt senere med et alternativ.
Avatar billede beef12 Nybegynder
21. juni 2006 - 11:19 #6
hmm - jeg kan ikke finde ud af hvordan man laver "top" i firebird. Det kune være du lave et nyt spørgsmål til netop dette issue.

Forstod du det der med Datediff, som jeg prøvede at forklare?
Avatar billede hrc Mester
21. juni 2006 - 12:27 #7
I Firebird er der faktisk muligt at lave "select first 1 ..." som jeg må antage gør det samme som "top" - men desværre findes den funktionalitet ikke i Interbase som vi også bruger.

Hvis det kan hjælpe på opgaven så har jeg nu gjort fradato-feltet tvungent. Ikke noget med at lede efter null-felter.

Hvad datefiff angår så kan jeg ikke helt se forskellen mellem "order by fradato" og så din funktion.

Ved du om MSSQL har en "COMPUTED BY" mulighed (i CREATE TABLE)? Det kan måske løses vha. et beregnet felt. Ret smart om man kunne kalde en procedure den vej fra, men det set det dog ikke ud til. En select er dog mulig og hvad sker der med et resultat der returnerer flere records. Vil Interbase/Firebird/MSSQL så vælge den første værdi eller vil de raise en exception... Det er noget jeg skal prøve.
Avatar billede beef12 Nybegynder
21. juni 2006 - 14:16 #8
Der er ikke nogen forskel - bare glem det der med datediff, det er levn fra mit første indlæg hvori jeg havde fejlfortolket dit spm. Så fradato er helt fint at anvende.

Held og lykke med det.
Avatar billede hrc Mester
22. juni 2006 - 08:20 #9
beef12: Jeg har måttet programmere mig ud af det, ikke optimalt, men jeg kan stå inde for det. I stedet for at du skal ligge vågen om natten for at finde en løsning så synes jeg at vi skal lukke spørgsmålet. Da opgaven ikke er blevet løst vil det være forkert at give fuld pointsantal, men smider du et svar, så kan du få de 25 for dit besvær. Håber det er OK.
Avatar billede beef12 Nybegynder
22. juni 2006 - 17:35 #10
Helt fint - jeg har ikke løst dit problem, så snup du bare alle points :-)

Og held og lykke med projektet.
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