Avatar billede bjornhart Nybegynder
27. oktober 2010 - 14:44 Der er 25 kommentarer og
1 løsning

reservationskonflikter

Hej

Jeg har en database som skal bruges til at reservere køretøjer i. Disse køretøjet kan ikke reserveres flere gange på samme tid, hvorfor det er nødvendigt at lave et sql udtræk som kan kontrollere om køretøjet er reserveret i forvejen. Dette udtræk kan jeg ikke finde ud af at lave og derfor beder jeg om hjælp.

Min reservationstabel ser således ud:

Køretøjsid, Nvarchar
ReservationsStartdato, datetime
ReservationsSlutdato, datetime

Har prøvet:

Select * from reservationstabel where Køretøjsid = @id AND ((@resvStartDato BETWEEN ReservationsStartdato AND ReservationsSlutdato) OR (@resvSlutDato BETWEEN ReservationsStartdato AND ReservationsSlutdato))

Den fungerer hvis Startdato eller slutdatoen for en reservation ligger mellem 07-09 men ikke hvis de ligger uden for ex. 0600-1000.

Nogen der har et bud?
Avatar billede bkp Nybegynder
27. oktober 2010 - 15:17 #1
Jeg går ud fra du mener 06-10?

Umiddelbart kan jeg ikke se hvor det går galt, er din @resvStartDato og @resvSlutDato også af typen DateTime?
Avatar billede bkp Nybegynder
27. oktober 2010 - 15:19 #2
Er der chance for at nogle af DateTime værdierne er null?

For så kan den ikke finde ud af det.
Avatar billede bkp Nybegynder
27. oktober 2010 - 15:33 #3
Jeg har lige nærlæst den igen, og jeg kan se at du har et problem ved at bruge Between da en reservation vel godt kan starte før en tidligere reservation og vare længere end den tidligere reservation, så jeg tror du er nødt til at lave nogle flere tjeks som f.eks:

(@resvStartDato < ReservationsStartdato AND @resvSlutDato >= ReservationsStartdato) Or

O.s.v.
Avatar billede bjornhart Nybegynder
27. oktober 2010 - 16:51 #4
Hej bkp


Ja lige netop en reaservation kan nemlig starte før og slutte efter en anden reservation

Ja de @resvStartDato og slut er af typen datetime.

Håbede lidt der var en som havde en komplet sql sætning da jeg er kørt fast
Avatar billede Syska Mester
27. oktober 2010 - 17:12 #5
Du mangler lidt info ...

Hvad er:
"Den fungerer hvis Startdato eller slutdatoen for en reservation ligger mellem 07-09 men ikke hvis de ligger uden for ex. 0600-1000."

Første virker som en dato, men det andet er et tidspunkt på en dag eller ?

Gerne lave et lille dump af din DB ... og struktur, så kan vi nemmere oprette det i vores ende, så vi ved præcis at vi arbejder på det samme.

Men går ud fra du vil tage alle de biler som er fri i den periode kunden vil leje en bil.

Ergo:
Tag alle biler hvor @resvStartDato er længere ude i fremtiden end slutdato
eller
Tag alle biler hvor @resvSlutDato er længere tilbage end startdato.

Select * from reservationstabel where Køretøjsid = @id
AND
(
ReservationsSlutdato <= @resvStartDato
OR
ReservationsStartdato >= @resvSlutDato
)

Kan ske jeg tager fejl ... træt.
Avatar billede bkp Nybegynder
27. oktober 2010 - 17:13 #6
Jeg vil tro at den her vil fange dem alle, prøv lige at teste flere eksempler, jeg tror det vil virke:

Select *
from
    @reservationstabel
where
    Køretøjsid = @id AND
    (
        (@slut < SlutDato AND @slut > StartDato) OR
        (@start < StartDato AND @slut > StartDato) OR
        (@start > StartDato AND @start < SlutDato)
    )
Avatar billede Syska Mester
27. oktober 2010 - 17:28 #7
Jeg vil stadig mene min er korrekt.

Eneste man vil er jo reelt set at finde ud af om bilen er ledig, og det er den kun hvis ens start er efter en anden resSlut ... og ens end er før ResStart.

Man så kan snakke om det skal være <= eller < og > ...

mvh
Avatar billede bkp Nybegynder
27. oktober 2010 - 17:34 #8
Der var vist en fejl i min forrige, jeg lavede denne test, og det ser ud til at være korrekt nu:

DECLARE @reservationstabel TABLE (
    Køretøjsid Nvarchar(10),
    StartDato datetime,
    SlutDato datetime
)
DECLARE @start DATETIME
DECLARE @slut DATETIME
DECLARE @id nvarchar(10)

SET @start = CAST('2010-10-20 06:00' AS DATETIME)
SET @slut = CAST('2010-10-20 10:00' AS DATETIME)
SET @id = 'testbil'

INSERT INTO @reservationstabel (Køretøjsid ,StartDato ,    SlutDato)
SELECT @id,CAST('2010-10-20 05:00' AS DATETIME),CAST('2010-10-20 07:00' AS DATETIME) UNION
SELECT @id,CAST('2010-10-20 06:00' AS DATETIME),CAST('2010-10-20 08:00' AS DATETIME) UNION
SELECT @id,CAST('2010-10-20 07:00' AS DATETIME),CAST('2010-10-20 09:00' AS DATETIME) UNION
SELECT @id,CAST('2010-10-20 08:00' AS DATETIME),CAST('2010-10-20 10:00' AS DATETIME) UNION
SELECT @id,CAST('2010-10-20 09:00' AS DATETIME),CAST('2010-10-20 11:00' AS DATETIME) UNION
SELECT @id,CAST('2010-10-20 10:00' AS DATETIME),CAST('2010-10-20 12:00' AS DATETIME) UNION
SELECT @id,CAST('2010-10-20 11:00' AS DATETIME),CAST('2010-10-20 13:00' AS DATETIME)

Select *
from
    @reservationstabel
where
    Køretøjsid = @id AND
    (
        (@slut < SlutDato AND @slut > StartDato) OR
        (@start <= StartDato AND @slut > StartDato) OR
        (@start > StartDato AND @start < SlutDato)
    )
Avatar billede bkp Nybegynder
27. oktober 2010 - 17:37 #9
Buzz >
Du har måske ret, men jeg forstod at han ville tjekke om bilen allerede var reserveret i et givent tidsrum, men hvis den skal vendes rundt, så man tjekker om den er ledig (hvilket er mere simpelt) så er din selvfølgelig rigtigt, men det er bare ikke det han spurgte efter ;-)
Avatar billede bjornhart Nybegynder
27. oktober 2010 - 18:11 #10
Jeg vil som bkp siger, checke om en bil er ledig i et givent tidsrum. Jeg prøver bkp's løsning i morgen, nr jeg igen er på arbejde og har adgang til databasen.
Avatar billede Syska Mester
27. oktober 2010 - 20:53 #11
Simpelt ... er der 1 row, så er den ledig, er der 0 rows så er den optaget.

Så er det jo bare at lave SELECT * om til SELECT COUNT(*)

mvh
Avatar billede bkp Nybegynder
27. oktober 2010 - 21:15 #12
Buzzzz >
Er det nu også rigtigt ;-)
Dit script kigger kun efter om der er reservationer uden for den valgte periode, den tjekker jo ikke om der tilfældigvis også er en reservation inden for perioden, så hvilket resultat vil dit script give hvis der både er en reservation uden for perioden og samtidig er reservation inden for perioden.
Tror efter længere spekulationer at min er den mest sikre måde ;-) HVIS du vil sikre dig at der ikke er reservationer i en given periode....
* Der tages forbehold for trykfejl (eller manglende logik), da jeg også er træt nu :-)
Avatar billede Syska Mester
27. oktober 2010 - 21:28 #13
Din sql er da også forkert så ...

Hvordan kan en bil være reserveret 2 gange inden for samme internal.

Dit sql giver:
testbil    2010-10-20 05:00:00.000    2010-10-20 07:00:00.000
testbil    2010-10-20 06:00:00.000    2010-10-20 08:00:00.000
testbil    2010-10-20 07:00:00.000    2010-10-20 09:00:00.000
testbil    2010-10-20 08:00:00.000    2010-10-20 10:00:00.000
testbil    2010-10-20 09:00:00.000    2010-10-20 11:00:00.000


Du har indsat:
testbil    2010-10-20 05:00:00.000    2010-10-20 07:00:00.000
testbil    2010-10-20 06:00:00.000    2010-10-20 08:00:00.000
testbil    2010-10-20 07:00:00.000    2010-10-20 09:00:00.000
testbil    2010-10-20 08:00:00.000    2010-10-20 10:00:00.000
testbil    2010-10-20 09:00:00.000    2010-10-20 11:00:00.000
testbil    2010-10-20 10:00:00.000    2010-10-20 12:00:00.000
testbil    2010-10-20 11:00:00.000    2010-10-20 13:00:00.000

En bil kan vel ikke være reserveret fra 05:00 til 07:00 ... da den også skal lejes ud fra 06:00 til 08:00

Så vil jeg i hvert fald være ham der henter den først :-) Så jeg kan få min bil, for ham der kommer 07:00 kan jo ikke få den som allerede er lejet ud.

mvh
Avatar billede Syska Mester
27. oktober 2010 - 21:32 #14
Min fejler også ... tænkte kun lige på en row :-)

mvh
Avatar billede Syska Mester
27. oktober 2010 - 21:38 #15
Den her burde virke ...

Hvis tidspunktet .. end start eller end er inden for den rækkefølge vil den returnere de rows, som gør at bilen ikke kan lejes ud:
DECLARE @reservationstabel TABLE (
    Køretøjsid Nvarchar(10),
    StartDato datetime,
    SlutDato datetime
)
DECLARE @Start DATETIME
DECLARE @End DATETIME
DECLARE @id nvarchar(10)

SET @Start = CAST('2010-10-20 08:01' AS DATETIME)
SET @End = CAST('2010-10-20 09:00' AS DATETIME)
SET @id = 'testbil'

INSERT INTO @reservationstabel (Køretøjsid ,StartDato ,    SlutDato)
SELECT @id,CAST('2010-10-20 04:00' AS DATETIME),CAST('2010-10-20 05:00' AS DATETIME) UNION
SELECT @id,CAST('2010-10-20 07:00' AS DATETIME),CAST('2010-10-20 08:00' AS DATETIME) UNION
SELECT @id,CAST('2010-10-20 10:00' AS DATETIME),CAST('2010-10-20 11:00' AS DATETIME) UNION
SELECT @id,CAST('2010-10-20 13:00' AS DATETIME),CAST('2010-10-20 14:00' AS DATETIME) UNION
SELECT @id,CAST('2010-10-20 16:00' AS DATETIME),CAST('2010-10-20 17:00' AS DATETIME) UNION
SELECT @id,CAST('2010-10-20 19:00' AS DATETIME),CAST('2010-10-20 20:00' AS DATETIME) UNION
SELECT @id,CAST('2010-10-20 22:00' AS DATETIME),CAST('2010-10-20 23:00' AS DATETIME)

Select *
from
    @reservationstabel
where
    Køretøjsid = @id AND
    (
        (@Start BETWEEN StartDato AND SlutDato)
        OR
        (@End BETWEEN StartDato AND SlutDato)
    )
Avatar billede bkp Nybegynder
27. oktober 2010 - 22:05 #16
Ja ja, mine testdata er uden logik, ved det godt.
Fokuserede mere på selve select statement ...
Men er træt nu, tjekker din udgave i morgen, men umiddelbart lyder det rigtigt.
Avatar billede Syska Mester
27. oktober 2010 - 22:14 #17
Men jeg tror nu også jeg ville opbygge sådan en table på en anden måde ... men igen, da jeg ikke har prøvet det endnu, ved jeg ikke om det bliver mere praktisk af den grund :-)

mvh
Avatar billede janus_007 Nybegynder
27. oktober 2010 - 23:32 #18
Hvis du ændrer dit tabeldesign vil det være 100 gange nemmere! Hvad siger du til det?
Avatar billede bkp Nybegynder
28. oktober 2010 - 07:55 #19
Buzz >
Har lige testet din version, den fanger ikke denne testværdi selvom den burde:

SELECT @id,CAST('2010-10-20 08:30' AS DATETIME),CAST('2010-10-20 08:45' AS DATETIME)

Beklager, men med den datamodel bjornhart har leveret er min test version den mest korrekte.

Viser den lige igen med bedre test data:

DECLARE @reservationstabel TABLE (
    Køretøjsid Nvarchar(10),
    StartDato datetime,
    SlutDato datetime
)
DECLARE @start DATETIME
DECLARE @slut DATETIME
DECLARE @id nvarchar(10)

SET @start = CAST('2010-10-20 09:01' AS DATETIME)
SET @slut = CAST('2010-10-20 10:00' AS DATETIME)
SET @id = 'testbil'

INSERT INTO @reservationstabel (Køretøjsid ,StartDato ,    SlutDato)
SELECT @id,CAST('2010-10-20 05:00' AS DATETIME),CAST('2010-10-20 06:00' AS DATETIME) UNION
SELECT @id,CAST('2010-10-20 06:00' AS DATETIME),CAST('2010-10-20 07:00' AS DATETIME) UNION
SELECT @id,CAST('2010-10-20 07:00' AS DATETIME),CAST('2010-10-20 08:00' AS DATETIME) UNION
SELECT @id,CAST('2010-10-20 08:00' AS DATETIME),CAST('2010-10-20 09:10' AS DATETIME) UNION
SELECT @id,CAST('2010-10-20 09:11' AS DATETIME),CAST('2010-10-20 09:25' AS DATETIME) UNION
SELECT @id,CAST('2010-10-20 09:26' AS DATETIME),CAST('2010-10-20 09:45' AS DATETIME) UNION
SELECT @id,CAST('2010-10-20 09:46' AS DATETIME),CAST('2010-10-20 10:10' AS DATETIME) UNION
SELECT @id,CAST('2010-10-20 10:11' AS DATETIME),CAST('2010-10-20 11:00' AS DATETIME) UNION
SELECT @id,CAST('2010-10-20 11:00' AS DATETIME),CAST('2010-10-20 12:00' AS DATETIME)

Select *
from
    @reservationstabel
where
    Køretøjsid = @id AND
    (
        (@slut < SlutDato AND @slut > StartDato) OR
        (@start <= StartDato AND @slut > StartDato) OR
        (@start > StartDato AND @start < SlutDato)
    )
Avatar billede Syska Mester
28. oktober 2010 - 08:54 #20
Jeg tror stadig vi må snakke forbi hinanden.

Kan ikke se hvad din fanger som min ikke gør ...
Avatar billede bkp Nybegynder
28. oktober 2010 - 09:00 #21
Buzzz >

Her er din kode, med lidt andet testdata, prøv at nærlæse den og kør den ;-)


DECLARE @reservationstabel TABLE (
    Køretøjsid Nvarchar(10),
    StartDato datetime,
    SlutDato datetime
)
DECLARE @Start DATETIME
DECLARE @End DATETIME
DECLARE @id nvarchar(10)

SET @Start = CAST('2010-10-20 08:01' AS DATETIME)
SET @End = CAST('2010-10-20 09:00' AS DATETIME)
SET @id = 'testbil'

INSERT INTO @reservationstabel (Køretøjsid ,StartDato ,    SlutDato)
SELECT @id,CAST('2010-10-20 07:00' AS DATETIME),CAST('2010-10-20 08:00' AS DATETIME) UNION
SELECT @id,CAST('2010-10-20 08:30' AS DATETIME),CAST('2010-10-20 08:45' AS DATETIME) UNION
SELECT @id,CAST('2010-10-20 10:00' AS DATETIME),CAST('2010-10-20 11:00' AS DATETIME) UNION

Select *
from
    @reservationstabel
where
    Køretøjsid = @id AND
    (
        (@Start BETWEEN StartDato AND SlutDato)
        OR
        (@End BETWEEN StartDato AND SlutDato)
    )
Avatar billede bjornhart Nybegynder
28. oktober 2010 - 09:26 #22
Det virker perfekt bkp! Tusind tak

janus_007. Jeg kan ikke se hvordan jeg kan lave mit tabeldesign om, så det ville blive meget nemmere, men vil meget gerne se dit bud.
Avatar billede bjornhart Nybegynder
28. oktober 2010 - 09:28 #23
Iøvrigt mange tak til alle der har bidraget i denne tråd.
Avatar billede Syska Mester
28. oktober 2010 - 09:39 #24
hahah, brian, nu kan jeg godt se hvor det går galt for min :-)

Som sagt ... alt for meget andet at se til i går :-) *heheh*

Men du kan jo skrive din query lidt om, og så bruge BETWEEN, så ser den lidt pænere ud.

mvh
Avatar billede bkp Nybegynder
28. oktober 2010 - 09:49 #25
Avatar billede Syska Mester
28. oktober 2010 - 09:59 #26
Så burde han jo slet ikke lave et reservations system, papiret har jo været brugt tidligere :-)
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