PDA

Vollständige Version anzeigen : Abfrage Problem - Reservierungszeiträume


N8Chatter
10.05.2004, 13:50
Hallo zusammen!

Ich habe folgendes Problem.
Eine Tabelle mit:
IDAppartement (Laufende Nummer)
von_Datum
bis_Datum


Ich möchte eine Abfrage erstellen, in der ALLE Datensätze auftauchen die in einem von mir angegeben Zeitraum nicht gebucht sind. Ich habe versucht es folgendermassen zu lösen:

SELECT tblAppartement.IDAppartement, tblAppartement.von_Datum, tblAppartement.bis_Datum
FROM tblAppartement
WHERE (((tblAppartement.von_Datum) Not Between [Buchung von:] And [Buchung bis:]) OR ((tblAppartement.bis_Datum) Not Between [Buchung von:] And [Buchung bis:]));


Leider funktioniert das so nicht, hat jemand ne andere Idee?
Danke für die Hilfe!

MfG
N8Chatter

N8Chatter
10.05.2004, 14:28
Wenn ich mich vielleicht ein wenig missverständlich ausgedrückt habe, bitte melden. :D

MfG
N8Chatter

Nouba
10.05.2004, 14:31
Versuchs mal so
SELECT DISTINCT
IDAppartement
FROM tblAppartment
WHERE (
[Buchung von:] <= [bis_Datum] And
[Buchung bis:] >= [von_Datum]
) = False

N8Chatter
10.05.2004, 14:39
Sauber!

Vielen Dank Nouba!
Haut hin :D :D

Johnny Loser
10.05.2004, 15:58
Möglicherweise irre ich mich, aber ich setze mal voraus, daß es mehrere Datensätze mit der gleichen IDAppartement in der Tabelle gibt, jeweils mit unterschiedlichen Buchungszeiträumen.

Ich stand vor einigen Jahren mal vor einem ähnlichen Problem und - ganz ehrlich - so, wie Nouba vorgeschlagen hat, läßt es sich wohl nicht so einfach lösen, auch wenn's auf den ersten Blick vielleicht so scheint.

Die Abfrage liefert lediglich als Ergebnis alle Buchungen die vorher enden, bzw. nachher beginnen. Ob oder ob keine Buchung in diesem Zeitraum existiert, siehst man dadurch nicht.

Um das gewünschte Ergebnis ("Welche App's sind im angegebenen Zeitraum frei?") heraus zu bekommen, sehe ich momentan keine andere Möglichkeit, als jedes App' in einer Funktion/Schleife abzuarbeiten und eine temporäre Tabelle zu füllen.

Ich habe seinerzeit das Konzept über den Haufen geworfen und pro ID/Datum einen Datensatz mit Status Ja/Nein angelegt. Durch kombinierten Index auf ID/Datum war ausgeschlossen, daß ein Tag doppelt erfasst werden konnte.

N8Chatter
10.05.2004, 17:00
Ja, stimmt. Jetzt, wo ich deinen Beitrag lese und das ganze einmal getestet habe, ist es tatsächlich so, dass es Probleme gibt.

Ärgerlich. Wie genau meinst du das mit der temporären Tabelle? Ist es zu aufwendig das hier einmal zu posten? Es handelt sich hierbei um eine Projektarbeit, dass mit den Reservierungszeiträumen ist im Moment das einzige woran ich hänge. Und Übermorgen ist Abgabetermin :eek:

Also wenn das nicht ganz so Aufwendig ist, dann wäre es nett wenn du mir einmal postest wie du das realisiert hattest. Ansonsten muss ich einmal schaun ob ich da mit mehreren Abfragen etwas zaubern kann..

----
Ach ja, die Tabelle ist natürlich ein wenig anders Aufgebaut. In der Tabelle Appartement sind natürlich keine Buchungszeiträume angegeben, die befinden sich in einer Tabelle 'Auftrag'. Ich habe das hier nur einfachheitshalber so dargestellt. Aber ioch denke das sollte klar sein :D

Dank Dir!
MfG

N8Chatter

Johnny Loser
10.05.2004, 18:15
So, sieht bei mir jetzt folgendermaßen aus:

Zusätzliche Tabelle "tblFreieApps", 1 Feld "ID" Long Integer

Formular

2 Felder "txVon" und "txBis", beide Format "Datum, kurz"
1 Button "btAnzeigen"
1 ListBox "LiApps", Herkunftstyp "Tabelle/Abfrage", Datenherkunft "SELECT ID FROM tblFreieApps ORDER BY ID"
zusätzlich ohne Verwendung einer temporären Tabelle
1 ListBox "LiApps2", Herkunftstyp "Werteliste", Datenherkunft ""

Option Compare Database
Option Explicit
'=========================================================================
Private Sub btAnzeigen_Click()
If Not IsDate(txVon) Or Not IsDate(txBis) Then
MsgBox "Datum fehlt", 48
Exit Sub
End If
If CDate(txVon) > CDate(txBis) Then
MsgBox "Von > Bis", 48
Exit Sub
End If
Dim rsApp As Recordset
Dim strSQL As String
CurrentDb.Execute ("DELETE FROM tblFreieApps"), dbFailOnError
LiApps2.RowSource = ""
Set rsApp = CurrentDb.OpenRecordset("SELECT IDAppartement AS ID FROM " _
& "tblAppartment GROUP BY IDAppartement")
'alternativ sollten die ID's aus der Appartment-Stammtabelle geholt werden
'habe ich mir für mein Beispiel gespart
rsApp.MoveFirst
Do While Not rsApp.EOF
strSQL = "IDAppartement = " & rsApp!ID & " AND (" _
& "(von_Datum <= " & GetSQLDate(CDate(txVon)) & " AND " _
& "bis_Datum >= " & GetSQLDate(CDate(txVon)) & ") OR " _
& "(von_Datum <= " & GetSQLDate(CDate(txBis)) & " AND " _
& "bis_Datum >= " & GetSQLDate(CDate(txBis)) & ") OR " _
& "(von_Datum >= " & GetSQLDate(CDate(txVon)) & " AND " _
& "bis_Datum <= " & GetSQLDate(CDate(txBis)) & "))"
If MCount("*", "tblAppartment", strSQL) = 0 Then
CurrentDb.Execute ("INSERT INTO tblFreieApps (ID) VALUES(" _
& rsApp!ID & ")"), dbFailOnError
LiApps2.RowSource = LIApps2.RowSource & rsApp!ID & ";"
End If
rsApp.MoveNext
Loop
rsApp.Close
Set rsApp = Nothing
LiApps.Requery
LiApps2.Requery
End Sub

'folgende Funktionen in einem Modul

'=========================================================================
Public Function GetSQLDate(OrgDate As Date, _
Optional DateLong As Boolean = False) As String
On Error Resume Next
If Not DateLong Then
GetSQLDate = Format(OrgDate, "\#mm\/dd\/yyyy\#")
Else
GetSQLDate = Format(OrgDate, "\#mm\/dd\/yyyy hh:nn:ss\#")
End If
End Function
'=========================================================================
Public Function MCount(Expression As String, Domain As String, _
Optional Criteria) As Variant
On Error Resume Next
Dim strSQL As String
strSQL = "SELECT Count(" & Expression & ") FROM " & Domain
If Not IsMissing(Criteria) Then strSQL = strSQL & " WHERE " & Criteria
MCount = DBEngine(0)(0).OpenRecordset(strSQL, dbOpenForwardOnly)(0)
If Err <> 0 Then MCount = Null
End Function

N8Chatter
10.05.2004, 18:33
Oha.. Na, da hab ich jetzt ja ein wenig was zu tun :D
Vielen Dank für die schnelle Antwort und die Mühe!

Ich werde das mal umsetzen und schauen ob es mit meiner DB funktioniert und dann nen Feedback geben :)

Nouba
11.05.2004, 05:54
Johnny hat natürlich berechtigte Zweifel an meiner oberflächlichen Antwort angemeldet. Unter der Prämisse, herauszufinden, welche Appartments zu einem Zeitraum buchbar sind, kann ein Outer Join von der Stammtabelle der Apartments auf die Buchungstabelle gesetzt werden und es sollte damit das korrekte Resultat aller freien Appartments erscheinen. Zusätzlich wird jedoch noch zu prüfen sein, ob einer der Daten(ums)angaben Null ist, was bei noch nie gebuchten Appartments der Fall sein würde. Dazu reicht es aus, an das Kriterium ein OR von_Datum Is Null (auf das bis_Datum könnte man sich auch beziehen) anzuhängen. Wie der Zeitraum zu überprüfen ist, mußt Du mit der Vermietungspraxis abstimmen - in der Regel dürfte das bis_Datum gleich dem von_Datum sein (zur Mittagszeit wird das Appartment verlassen und am selben Tag kann auch ein Neubezug erfolgen). Ansonsten kann man auch wie im Beispiel die Uhrzeit mit einbeziehen, um Überlappungen zu verhindern.

Eine Formularlösung ist natürlich eine praxisgerechtere Lösung als Parameter in einer Abfrage zu verwenden.

Johnny Loser
11.05.2004, 06:13
Ich sehe bei diesem Daten-Konzept einen grundsätzlichen Nachteil.

Es besteht die theoretische Möglichkeit, in der Tabelle Doppelbelegungen einzutragen.

Angenommen 2 Sachbearbeiter erhalten gleichzeitig eine Anfrage über denselben Zeitraum und beide Kunden entscheiden sich für dasselbe Appartment. In diesem Fall müßte vor dem Speichern nochmals geprüft werden, ob sich die Daten zwischenzeitlich geändert haben.

Nouba
11.05.2004, 06:32
In einer Mehrbenutzerumgebung müßte man sehr wohl nochmals eine Prüfung vor dem Schreiben der Daten einpflegen, was aber auch für Dein Beispiel, wenn ich es richtig verstehe, gelten dürfte. Am Sichersten dürfte es vermutlich sein, jeden belegten Tag (ohne Uhrzeit in diesem konkreten Fall) einzeln in einer Tabelle zu verbuchen und einen zusammengesetzen eindeutigen Index über AppartmentID und Buchungstag zu verwenden.

Johnny Loser
11.05.2004, 06:34
@Nouba

Zu diesem Schluß bin ich seinerzeit auch gekommen und habe mein Konzept dahingehend geändert

N8Chatter
12.05.2004, 15:16
So, zunächst einmal möchte ich euch beiden nochmals für die Hilfe danken!

Leider bin ich weder mit der einen, noch mit der anderen Lösung rechtzeitig fertig geworden, was allerdings allein daran lag, dass sich Probleme mit weiteren Tabellen aufgetan haben. Die Reservierungszeiträume galten für Appartements, Parkplätze, welche dazu zählten (oder eben auch nicht) und auch für Touristenführungen.

Wie gesagt handelt(e) es sich hierbei um ein Schulprojekt mit Abgabetermin heute. Da es ein zu großer Aufwand geworden wäre die Lösungen auf alle Bereiche auszuweiten, habe ich darauf verzichtet es so komfortabel zu gestalten, das falsche Eingaben einfach nicht möglich sind. Ich habe mich aus Zeitmangel einfach auf eine jeweilige, monatliche Übersicht beschränkt, so dass der User selbst gucken muss wann etwas frei ist und wann nicht.

Zumindest ist die DB so auch Einsatzbereit, und fertig wird man mit sowas ja sowieso nie :D


Ich werde allerdings beide Vorschläge weiter bearbeiten, um es nun doch so komfortabel zu machen wie irgendmöglich.

Also, vielen Dank an euch!