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

werner_sg

Erfahrenes Mitglied
Hallo ich hole mir mit folgendem Code alle daten einer Spalte in eine Checkbox, was so fehlerfrei funktioniert.

Code:
        conn.Open()

        Try
            dbcmd = New OleDbCommand("SELECT * FROM tblfahrzeuge", conn)
            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

        Try
            dbcmd = New OleDbCommand("SELECT * FROM tblmieter", conn)
            Dim DbReader As OleDbDataReader

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

        conn.Close()

ich möchte aber das alle Fahrzeuge zwischen zwei Datumsfeldern nicht mitgeladen werden

Die Felder im Program sind DataTimePicker1 und DataTimePicker3 und die Spalten in der Tabelle tblreservierung sind ABHOLUNG_DATUM und ABGABE_DATUM

hierzu habe ich es dann mit folgendem String versucht

(SELECT * FROM tblfahrzeuge, tblreservierung WHERE KFZ_NAME = KFZ_NAME WHERE '" & DateTimePicker1.Value & "' AND '" & DateTimePicker3.Value & "' NOT BETWEEN ABHOLUNG_DATUM AND ABGABE_DATUM , conn)

Dabei erhalte ich die Fehlermeldung : Syntayfehler (fehlender Operator) in Abfrageausdruck WHERE KFZ_NAME = KFZ_NAME WHERE 22.06.2021 17:05:33 AND 26.06.2021 18:06:12' NOT BETWEEN ABHOLUNG_DATUM AND ABGABE_DATUM

welcher Operator fehlt? Die beiden Zeiten aus den Pickern werden ja richtig übergeben
 
Lösung
1624480918307.png
Doch wieder als String?
Was machen die = im Between?
Was soll das Format DD-MM-YYYY in den Fixen Datumswerten? Entweder MM/DD/YYYY oder YYYY-MM-DD.

Visual Basic:
'Wert aus DateTimePicker1 als SQL-String
sqlStrDt1 = "#" & DateTimePicker1.Value.ToString("yyyy-MM-dd H:mm:ss") & "#"
sqlStrDt2 = "#" & DateTimePicker2.Value.ToString("yyyy-MM-dd H:mm:ss") & "#"
'Hier kannst du sqlDt1 debuggen. Schauen mal wie die aussehen

'Das SQL zusammenstellen
sql = "SELECT *  " &
    "FROM tblfahrzeuge  " &
    "WHERE  " &
    "    KFZ_NAME NOT IN ( " &
    "        SELECT KFZ_NAME " &
    "        FROM tblreservierung " &
    "          WHERE " &
    "             ( " & sqlStrDt1 & " BETWEEN abholung_datum AND abgabe_datum) " &
    "            OR ( "...
1624480918307.png
Doch wieder als String?
Was machen die = im Between?
Was soll das Format DD-MM-YYYY in den Fixen Datumswerten? Entweder MM/DD/YYYY oder YYYY-MM-DD.

Visual Basic:
'Wert aus DateTimePicker1 als SQL-String
sqlStrDt1 = "#" & DateTimePicker1.Value.ToString("yyyy-MM-dd H:mm:ss") & "#"
sqlStrDt2 = "#" & DateTimePicker2.Value.ToString("yyyy-MM-dd H:mm:ss") & "#"
'Hier kannst du sqlDt1 debuggen. Schauen mal wie die aussehen

'Das SQL zusammenstellen
sql = "SELECT *  " &
    "FROM tblfahrzeuge  " &
    "WHERE  " &
    "    KFZ_NAME NOT IN ( " &
    "        SELECT KFZ_NAME " &
    "        FROM tblreservierung " &
    "          WHERE " &
    "             ( " & sqlStrDt1 & " BETWEEN abholung_datum AND abgabe_datum) " &
    "            OR ( " & sqlStrDt2 & " BETWEEN abholung_datum AND abgabe_datum) "
'Das SQL debuggen

'Das SQL ausführen
dbcmd = New OleDbCommand(sql, conn)

Weiterer Tipp: SQL debuggen unter VBA/Access. Sollte für VB.Net ähnlich fubktioneren: [VBA][Access] Debug Queries [Yaslaw.Info]

Ps: Gute Besserung
 
Lösung
Anhang anzeigen 66641
Doch wieder als String?
Was machen die = im Between?
Was soll das Format DD-MM-YYYY in den Fixen Datumswerten? Entweder MM/DD/YYYY oder YYYY-MM-DD.

Visual Basic:
'Wert aus DateTimePicker1 als SQL-String
sqlStrDt1 = "#" & DateTimePicker1.Value.ToString("yyyy-MM-dd H:mm:ss") & "#"
sqlStrDt2 = "#" & DateTimePicker2.Value.ToString("yyyy-MM-dd H:mm:ss") & "#"
'Hier kannst du sqlDt1 debuggen. Schauen mal wie die aussehen

'Das SQL zusammenstellen
sql = "SELECT *  " &
    "FROM tblfahrzeuge  " &
    "WHERE  " &
    "    KFZ_NAME NOT IN ( " &
    "        SELECT KFZ_NAME " &
    "        FROM tblreservierung " &
    "          WHERE " &
    "             ( " & sqlStrDt1 & " BETWEEN abholung_datum AND abgabe_datum) " &
    "            OR ( " & sqlStrDt2 & " BETWEEN abholung_datum AND abgabe_datum) "
'Das SQL debuggen

'Das SQL ausführen
dbcmd = New OleDbCommand(sql, conn)

Weiterer Tipp: SQL debuggen unter VBA/Access. Sollte für VB.Net ähnlich fubktioneren: [VBA][Access] Debug Queries [Yaslaw.Info]

Ps: Gute Besserung
So ähnlich hatte ich es schon mal der Fehler dabei waren die # welche ich nicht in "" gesetzt hatte :)

habs jetzt noch deklariert und die Zeit entfernt und es arbeitet schon mal

Code:
        Dim sqlStrDt1 = "#" & DateTimePicker1.Value.ToString("yyyy-MM-dd ") & "#"
        Dim sqlStrDt2 = "#" & DateTimePicker2.Value.ToString("yyyy-MM-dd ") & "#"

        conn.Open()

        Try

            dbcmd = New OleDbCommand("SELECT * FROM tblfahrzeuge  " &
            " WHERE  KFZ_NAME NOT IN  " &
            " (SELECT KFZ_NAME FROM tblreservierung " &
            " WHERE(" & sqlStrDt1 & " BETWEEN ABHOLUNG_DATUM And ABGABE_DATUM) " &
            " Or ( " & sqlStrDt2 & " BETWEEN ABHOLUNG_DATUM And ABGABE_DATUM))", conn)

            'dbcmd = New OleDbCommand(Sql, conn)

gibt es eine Alternative zu Between? welche mir nicht nur dazwischen sondern auch den ersten und letzten Tag mit auswertet

jetzt arbeitet es so das bei einer bestehenden Reservierung vom 25.08.2021 bis 28.08.2021
und einer Abfrage vom 01.08.2021 bis 25.08.2021 mir das fahrzeug als verfügbar anbietet
bei einer Abfrage bis 26.08.2021 dann nicht mehr da dies erst dazwischen liegt.

Denke mal einfach eine neue deklaration wo ich dann bei sqlStrDt1 1 abziehe und bei sqlStrDt2 dann 1 zu zähle wird ja kaum funktionieren wenn ich das mit der Daten Übergabe aus Access richtig verstanden habe würde ich ja dann bei 25.08,2021 übergebener Wert 25082021 anschließend 25082020 erhalten, oder?

Eventuell aber mit dem Wert 1000000 dann dürfte ja aus 25082021, 24082021 werden

werde es mal testen, vieleicht klappt es ja
 
Between ist immer einschließlich.
ansonsten anstatt dem BETWEEN musst du die Vergleiche selbst machen.

EDIT: Dass es dir das Fahrzeug zum 25.08.2021 als verfügbar anbietet kann nur ein Zeitfaktor sein, der reinpfuscht.
Beispiel: In der DB steht für ABHOL_DATUM "2021-08-25 14:37:46" drin (Kunde hat am 25.08.2021 um 14:37 Uhr abgeholt), dein DatePicker liefert aber "2021-08-25 09:08:37", weil du morgens die Abfrage machst , womit ein BETWEEN erkennt, dass "2021-08-25 09:08:37" vor "2021-08-25 14:37:46" liegt, und es dir (korrekt!) als verfügbar liefert.
Müsstest mal schauen, ob Access eine Funktion anbietet, mit welchem man einen DateTime truncaten kann
What's the correct SQL query to retrieve date field without time? C# MS Access
Nachteil: Du bist wieder bei Strings

EDIT2: Mal testen. Aufpassen, ob Rundungsfehler auftauchen
Convert datetime to integer
 
Zuletzt bearbeitet:
Between ist immer einschließlich.
ansonsten anstatt dem BETWEEN musst du die Vergleiche selbst machen.

EDIT: Dass es dir das Fahrzeug zum 25.08.2021 als verfügbar anbietet kann nur ein Zeitfaktor sein, der reinpfuscht.
Beispiel: In der DB steht für ABHOL_DATUM "2021-08-25 14:37:46" drin (Kunde hat am 25.08.2021 um 14:37 Uhr abgeholt), dein DatePicker liefert aber "2021-08-25 09:08:37", weil du morgens die Abfrage machst , womit ein BETWEEN erkennt, dass "2021-08-25 09:08:37" vor "2021-08-25 14:37:46" liegt, und es dir (korrekt!) als verfügbar liefert.
Müsstest mal schauen, ob Access eine Funktion anbietet, mit welchem man einen DateTime truncaten kann
What's the correct SQL query to retrieve date field without time? C# MS Access
Nachteil: Du bist wieder bei Strings

EDIT2: Mal testen. Aufpassen, ob Rundungsfehler auftauchen
Convert datetime to integer

Hatte den Test eigentlich direkt nach dem Anlegen gemacht, damit war der Zeitfaktor ja auf jeden Fall Between weil er ein paar Minuten später war.

etwas überschlafen wirkt der Fehler gar nicht mal tragisch, es besteht ja die möglichkeit das er um 8 wieder abgegeben wird und dann ab 10 wieder verfügbar währe.

werde mir einach noch ne if Abfrage einbauen welche kontrolliert ob Abhol oder Abgabe Daten in Picker oder Tabelle gleich sind und dann gegebenenfals ein Message anzeigen wann das fahrzeug abgeholt oder gebracht wird.
 
ToString("yyyy-MM-dd ")
Das Leerzeichen raus. Mit dem Leerzeichen ist es kein sauberes SQL-Date

Zur Problematik Nur Dateum und Datum mit Zeit ein wenig Theorie:
Es ist wie von Zvoni beschrieben. Wenn in der Tabelle zB steht: #2021-06-23 09:10:10# dann ist das grösser als #2021-06-23#.
Ein Datum wird im Hintrgrund als Zahl mit Kommas gespeichert. Ganzzahlen sind das Datum (Im Access Tage seit 30.12.1899). Die Kommazahlen ist die Zeit. Mit dieser Zahl wird auch der Between ausgeführt. Wie du am folgenden Beispiel siehst, ist es klar dass das reine Datum kleiner ist als das Datum+Zeit und darum "rausfällt"
Visual Basic:
'VBA-Test im Access-VB-Direktfenster
?cdbl(#2021-06-23 09:10:10#)
 44370.3820601852
?cdbl(#2021-06-23#)
 44370

'Ergibt den SQL-Vergleich, der selbstverständliche FALSE ist
44370 BETWEEN 44370.3820601852 AND 44372.123456

Um die DB-Felder auf das Datum zu reduzieren kannst due DateValue() verwenden, Das extrahiert aus einem DateTime das Date
Visual Basic:
'Leerzeichen nach dd entfernen
 Dim sqlStrDt1 = "#" & DateTimePicker1.Value.ToString("yyyy-MM-dd") & "#"

'DateValue() auf die Tabellenfelder anwenden wenn du OHNE die Zeit vergleichen willst
" WHERE(" & sqlStrDt1 & " BETWEEN datevalue(ABHOLUNG_DATUM) And datevalue(ABGABE_DATUM)) " &
 
Vorsicht mit dem DateValue!
Wenn ich mich recht erinner, gibt es in Access viele Funktionen, welche auch tatsächlich nur in Access funktionieren, und nicht von "aussen" (wie in dem Fall VB.NET) benutzt werden können.
"Klassiker" ist hier die Replace-Funktion
SELECT REPLACE(EinText, "Finde", "Ersetze") FROM Tabelle funktioniert nur in Access selbst, nicht von aussen.
Würde mich nicht wundern, wenn DateValue zu dieser Gruppe Funktionen gehört
 
ToString("yyyy-MM-dd ")
Das Leerzeichen raus. Mit dem Leerzeichen ist es kein sauberes SQL-Date

Zur Problematik Nur Dateum und Datum mit Zeit ein wenig Theorie:
Es ist wie von Zvoni beschrieben. Wenn in der Tabelle zB steht: #2021-06-23 09:10:10# dann ist das grösser als #2021-06-23#.
Ein Datum wird im Hintrgrund als Zahl mit Kommas gespeichert. Ganzzahlen sind das Datum (Im Access Tage seit 30.12.1899). Die Kommazahlen ist die Zeit. Mit dieser Zahl wird auch der Between ausgeführt. Wie du am folgenden Beispiel siehst, ist es klar dass das reine Datum kleiner ist als das Datum+Zeit und darum "rausfällt"
Visual Basic:
'VBA-Test im Access-VB-Direktfenster
?cdbl(#2021-06-23 09:10:10#)
 44370.3820601852
?cdbl(#2021-06-23#)
 44370

'Ergibt den SQL-Vergleich, der selbstverständliche FALSE ist
44370 BETWEEN 44370.3820601852 AND 44372.123456

Um die DB-Felder auf das Datum zu reduzieren kannst due DateValue() verwenden, Das extrahiert aus einem DateTime das Date
Visual Basic:
'Leerzeichen nach dd entfernen
 Dim sqlStrDt1 = "#" & DateTimePicker1.Value.ToString("yyyy-MM-dd") & "#"

'DateValue() auf die Tabellenfelder anwenden wenn du OHNE die Zeit vergleichen willst
" WHERE(" & sqlStrDt1 & " BETWEEN datevalue(ABHOLUNG_DATUM) And datevalue(ABGABE_DATUM)) " &
Also ich habe dann mal das Leerfeld entfernt, Ergebnis funktioniert wieder nicht :unsure:
Dann noch mal alles kontrolliert und auf Datum Short eingestellt, immer noch Fehler :unsure:
Jetzt noch mal die Leerfelder reingesetzt, und alles Funktioniert jetzt Fehlerfrei o_O
Frag mich nicht warum, für manches gibt es keine Logik
 
Zurück