Zeitspanne vergleichen und entsprechende Datensätze nicht zeigen Access und VB.Net

Status
Dieses Thema wurde gelöst! Zur Lösung gehen…

werner_sg

Erfahrenes Mitglied
Sehe übrigens nochwas in seinem SQL (Post #5):
Er hat Abgabe_datum links im Between
Ich glaube mich daran zu erinnern, dass im BETWEEN links der kleiner Wert zu stehen hat und rechts der grössere.
Mag mich aber auch irren

Die Codesnipsel habe ich ja schon gepostet spare ich mir dann jetzt mal.

Ich habe zwei DateTimePicker,
DateTimePicker1 ist für das Anfangsdatum und DateTimePicker3 für das Enddatum

dazu habe ich eine Combobox cboxFahrzeug

und die Daten liegen in einer Access Datenbank mit den Tabellen tblfahrzeuge und tblreservierungen

beide Tabellen verfügen über eine Spalte mit KFZ_NAME die Tabelle tblreservierungen hat die beiden Datumsfelder ABHOLUNG_DATUM und ABGABE_DATUM

zur Zeit ist Testweise nur ein Fahrzeug in der Tabelle tblfahrzeuge vorhanden und noch keine Daten in Tabelle tblreservierungen

Ich möchte das geprüft wird ob zum ausgewählten Zeitraum von DateTimePicker1 und DateTimePicker3
bereits eine reservierung für ein Fahrzeug vorliegt, wenn ja soll dieses in der ComboBox nicht angezeigt werden und wenn nicht soll es angezeigt werden.

Da derzeit ja noch gar keine reservierungen eingetragen sind sollte der Eintrag aus tblfahrzeuge eigentlich angezeigt werden

Zusammengefasst

Datum Anfang wählen und Datum Ende wählen liegt Anfang oder Ende zwischen einer Reservierung in der Tabelle tblreservierung dann soll das dazugehörende Fahrzeug in der ComboBox nicht aufgelistet werden ansonsten soll es verfügbar sein.

mit bestem gruß Werner
 

werner_sg

Erfahrenes Mitglied

Zvoni

Erfahrenes Mitglied
Aus deinem zweiten Versuch
Code:
dbcmd.Parameters.AddWithValue("@KFZ_ABHOLUNG", DateTimePicker1.Value.ToString)
            dbcmd.Parameters.AddWithValue("@KFZ_ABGABE", DateTimePicker3.Value.ToString)

Aus deinem zusammengebautem SQL sind es die Apostrophe.
Yaslaw hat gezeigt, wie man bei Access ein Datum einklammern muss (mit Raute #)

EDIT: Nur ein Satz in der Datenbank ist aber nicht ausreichend um sowas zu testen.
Füge mal so mindestens mal 10 Sätze hinzu, wovon du mindestens 3 mit Reservierungen versiehst für unterschiedliche Zeiträume, inkl. überlappender Zeiträume

EDIT2: hab gerade deinen letzten Absatz in Post #11 gelesen.
Beispiel:
Es gibt bereits für Kunde Müller eine Reservierung für BMW320 vom 01.07.2021 bis 15.07.2021
Kunde Meier ruft an, und will ein Auto mieten vom 25.06.2021 bis 03.08.2021 (DatePicker1 bzw. DatePicker3)
Beide Werte der DatePicker sind NICHT BETWEEN der Reservierung, und würde dir als "verfügbares" Fahrzeug angezeigt werden.
Ich glaube der richtige Ansatz ist eher zu prüfen, ob zwischen beiden Zeiträumen eine Überlappung besteht.
Im Prinzip also das BETWEEN muss umgedreht werden: Liegt ABHOL_DATUM/ABGABE_DATUM zwischen DP1/DP3

EDIT3: Mein EDIT2 ist auch Quatsch. Dreht das Problem nur um. Ich mach nen neuen Post
 
Zuletzt bearbeitet:

Zvoni

Erfahrenes Mitglied
Arggh....MIST!
Denkfehler.
Habs jetzt. Weil wir die ganze Zeit uns auf das BETWEEN konzentriert haben, ist es mir entgangen, wo der Denkfehler ist.

Beide DatePicker müssen entweder beide VOR dem ABHOL_DATUM sein, oder beide müssen NACH dem ABGABE_DATUM sein. Jede andere Kombination hat eine Überlappung zufolge.
BETWEEN ist der gänzlich falsche Operator hier.

EDIT
Ausserdem würde ich eher einen INNER JOIN statt eines LEFT JOINS nehmen.

EDIT2
Ein Fahrzeug kann ja mehrere Reservierung bereits haben
Beispiel: Müller reserviert BMW320 vom 01.07.2021 bis 15.07.2021 und vom 01.08.2021 bis 15.08.2021
Meier will reservieren für 10.07.2021 bis 20.07.2021.
Die erste Reservierung schliesst den BMW320 aus, die zweite lässt ihn jedoch zu!
Ich glaube wir müssen die Vergleichskriterien umdrehen (und somit auch wieder den BETWEEN benutzen), um die ID des Fahrzeugs zu ermitteln, um dann am Ende per "... KFZ_NAME NOT IN (SELECT blablabla)" das Auto komplett rauszuwerfen.

Würde auf sowas hinauslaufen (Aircode)
SQL:
SELECT * FROM
Fahrzeuge
WHERE
KFZ_NAME NOT IN
(SELECT KFZ_NAME FROM Reservierung WHERE (DatePicker1 BETWEEN ABHOL_DATUM UND ABGABE_DATUM) OR (DatePicker2 BETWEEN ABHOL_DATUM AND ABGABE_DATUM)
Ich weiss jetzt allerdings nicht, ob Access "... NOT IN ..." unterstützt. Sonst kann man einen LEFT JOIN mit ISNULL auf der rechten Seite verwenden.

Hätten wir echte Beispieldaten, würde ich wahrscheinlich keine 10 Minuten brauchen, um dir die SQL-Abfrage zusammen zu bauen
 
Zuletzt bearbeitet:

Yaslaw

n/a
Moderator
mit : " ('" & DateTimePicker1.Value & "' BETWEEN ABGABE_DATUM AND ABHOLUNG_DATUM) " &

übernehme ich doch das datum aus dem Picker als Datum und nicht als String und die beiden Spalten aus der Tabelle werden doch auch nicht zum String umgewandelt oder?
Nein. Ich habe weiter oben erklkrt wie in Access das Datum für das SQL formatiert werden muss. Alles wa da mit ' oder " beginnt ist STRING und nicht DATE. Da wird aus einem Datum ein STRING gemacht. Glaub es mir oder lass es sein, mir ist das egal. Meine Erfahrung seit Access Version 1.0 sagt mir, dass das zu 90% keine Treffer geben wird.

Zum Thema Date/String ist von meiner Seite aus alles gesagt. Nimm es dir zu Herzen oder wurstle einfach weiter. Viel Glück.
 

werner_sg

Erfahrenes Mitglied
Nein. Ich habe weiter oben erklkrt wie in Access das Datum für das SQL formatiert werden muss. Alles wa da mit ' oder " beginnt ist STRING und nicht DATE. Da wird aus einem Datum ein STRING gemacht. Glaub es mir oder lass es sein, mir ist das egal. Meine Erfahrung seit Access Version 1.0 sagt mir, dass das zu 90% keine Treffer geben wird.

Zum Thema Date/String ist von meiner Seite aus alles gesagt. Nimm es dir zu Herzen oder wurstle einfach weiter. Viel Glück.
Glaube ich Dir zu 199% dafür hast Du mir in den letzten Jahren immer wieder zu gute Tips gegeben als das ich das anzweifle

Ich hatte dich so verstanden das es von dem DateTimePicker eventuell falsch kommt und nicht von der Access Seite
 

Yaslaw

n/a
Moderator
Datum als SQL-String müsste dann im US- oder ISO-Format vorliegen, begrenz mit # anstelle von '
SQL:
-- ISO YYYY-MM-DD HH:NN:SS
MY_DATE_FIELD = #2021-06-23 10:54:15#

-- US MM/DD/YYYY HH:NN:SS
MY_DATE_FIELD = #06/23/2021 10:54:15#
Der DatePicker liefert ein Datum. Und du setzt das einfach in ohne spezielle Formatierung in ein String - wer weiss schon was denn da steht?
Im SQL packst du dann das Datum in '. Aber es muss in # sonst ist es für die DB ein Text und kein Datum.
MS Access SQL hat eine ganz klare Vorstellung wie ien Datum in einem SQL-String geschrieben werden muss. Zum Glück hat es dass, sonst währe viel Zufall dabei. Beispiel das für eine klare Definition spricht:
Code:
//Der Datumstring
06/07/2021
--Ist je nach Länderinstellung
6. Juli 2021
7. Juni 2021
 

werner_sg

Erfahrenes Mitglied
Der DatePicker liefert ein Datum. Und du setzt das einfach in ohne spezielle Formatierung in ein String - wer weiss schon was denn da steht?
Ich :)
Aber auch nur weil er es mir in der Fehler Meldung angezeigt hat beim testen mit dem Between ;)
Die DateTimePicker liefern 21.06.2021 10:05:45 also das Datum mit Uhrzeit im Format wie wir es gewohnt sind, obwohl es damit eigentlich auch nicht macht was ich möchte habe es auf ja auf DateTimePickerFormat.Short stehen angezeigt wird es als solche aber der Value ist komplett mit Zeit
 

Yaslaw

n/a
Moderator
"Datum mit Uhrzeit im Format wie wir es gewohnt"
Jepp, das ist schön für dich um die Meldung zu lesen. Access bist aber nicht du. Access will es im ISO oder US Format, Begrenuzt durch #. Kaum machst du das Datum in ', dann macht Access ein STRING-Vergleich. Er wandelt also das Datum in einen String. Das ergibt viele Probleme.

Der Datepicker gibt dir "21.06.2021".
Die DB hat im Feld den 18te Juni. Access SQL macht daraus intern "06/18/2021" oder "2021-06-18", ich weiss es nicht. Das macht Access, weil es das Datum des Feldes mit einem String vergleichen muss, da Access den eingegeben Wert anhand der ' als String erkennt.
Jetzt vergleichen wir "21.06.2021" > "06/18/2021". Gibt selbstverständliche False zurückt, da das 2te Argument mit 0 beginnt. und 0 kleiner ist als 2 Also ein reiner Textvergleich.

Ev habe ich dir schon mal gesagt, mit preapred Statement kann man das umgehen. Oder wenn man Strings zusammensetzen will, dann mit SQL-Datumsformat und # als Begrenzer.

Ps. Ich würde es mal mit # als Begrenzer probieren
PPS. Achja, fast hätte ich es vergesen. Das Format sollte YYYY-MM-DD oder MM/DD/YYYY sein.
PPPS. Nicht vergessen, das ganze mit # begrenzen
PPPPS. Stringvergleiche funktionieren nicht. Wandle dein Datepicker ins Format #YYYY-MM-DD# oder arbeite mit Prepared Statement.
 

werner_sg

Erfahrenes Mitglied
OK arbeite immer noch drann :unsure:

Code:
    Private Sub DateTimePicker1_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles DateTimePicker1.ValueChanged

        CboxFahrzeug.Items.Clear()
        CboxFahrzeug.Text = Nothing

        conn.Open()


        Try
            'dbcmd = New OleDbCommand("SELECT * FROM tblfahrzeuge", conn)

            dbcmd = New OleDbCommand(" SELECT * " &
                                     " FROM " &
                                     "tblfahrzeuge " &
                                     " WHERE " &
                                     " KFZ_NAME NOT IN " &
                                     "(SELECT KFZ_NAME" &
                                     " FROM " &
                                     "tblreservierung " &
                                     " WHERE " &
                                     " ('" & DateTimePicker1.Text & "'= #01-05-2021#  BETWEEN ABHOLUNG_DATUM= #01-05-2021# AND ABGABE_DATUM= #01-05-2021#) " &
                                     " Or ('" & DateTimePicker3.Text & "'= #01-05-2021#   BETWEEN ABHOLUNG_DATUM= #01-05-2021# AND ABGABE_DATUM= #01-05-2021#))", conn)

            'dbcmd.Parameters.AddWithValue("@Start", DateTimePicker1.Value.ToString)
            'dbcmd.Parameters.AddWithValue("@Ende", DateTimePicker3.Value.ToString)


            Dim DbReader As OleDbDataReader

            DbReader = dbcmd.ExecuteReader
            While DbReader.Read
                CboxFahrzeug.Items.Add(DbReader("KFZ_NAME").ToString)
            End While
        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try


        conn.Close()
    End Sub

in der jetztigen Version gibt er mir den gewünschten Eintrag soweit keine Reservierung vorliegt, sobald ein Eintrag in der Tabelle tblreservierung besteht wird kein Fahrzeug mehr angezeigt egal zu welchem Datum

CboxFahrzeug.Items.Clear()
CboxFahrzeug.Text = Nothing

habe ich hinzugefügt da er ohne dieses wenn kein Eintrag in tblreservierung vorlag die Liste immer um die Menge in der Datenbank erhöht hat so werden die bestehenden Items in der Combobox erstmal entfernt

Mache also immer noch einen Fehler, den ich noch nicht verstehe

Bin gerade ehrlich gesagt auch etwas langsam im Denken, hab mir einen Rückennerv unter dem Muskel eingeklemmt und durch die Schmerzmittel etwas blöd im Hirn o_O aber die verordnete Bettruhe ist die beste Zeit für sowas :giggle:
 
Status
Dieses Thema wurde gelöst! Zur Lösung gehen…