SQLite Datumsabfragen

Für Themen zu Datenbanken und Zugriff auf diese. Auch für Datenbankkomponenten.
Antworten
RuhrPotto
Beiträge: 39
Registriert: Mi 6. Mai 2015, 12:52

SQLite Datumsabfragen

Beitrag von RuhrPotto »

Hallo zusammen!

Hab mal wieder ein Brett vorm Kopf ...

Ich versuche eine Abfrage mit einem Datumsbereich zu erstellen und bekomme dabei kein Ergebnis. Weder über die SQL im Programm noch über SQLite-Konsole.
Die Abfragen:

Code: Alles auswählen

 
1. sqlite> SELECT DATE(Datum), Art, Betrag FROM tBuchung WHERE ART = 0;
 
2. sqlite> SELECT DATE(Datum), Art, Betrag FROM tBuchung WHERE  Datum >= '2015-01-01';
 
3. sqlite> SELECT DATE(Datum), Art, Betrag FROM tBuchung;
2015-09-07|0|100
2015-09-07|1|40
2015-08-31|0|2000
2015-09-01|11|100
2015-09-01|10|100
2015-09-02|11|40
2015-09-02|10|40
2015-09-06|1|55
 

Abfrage 1 liefert ein Ergebnis; Abfrage 2 nicht, d.h. eine leere Menge und es gibt auch keinen Fehlercode.

Ich habe das Datum schon unteschiedlich geschrieben '2015-01-01' "2015-01-01" DATE( '2015-01-01') .. aber immer ohne Ergebnis.

Erstaunlicherweise liefert diese SQL eine Ergebnis im Programm

Code: Alles auswählen

//'SELECT TOTAL(Betrag) FROM tBuchung WHERE '
  //                    + 'Datum >= (:FIRST) AND '
  //                    + 'Datum <= (:LAST) AND '
  //                    + 'Art = 0';
  //SqlQueryB.ParamByName('FIRST').AsDateTime := MFirst;
  //SqlQueryB.ParamByName('LAST').AsDateTime  := MLast;   


Hat jemand dafür eine Erklärung bzw. kann mir jemand erklären, wie der Datumsstring aufgebaut sein muss, damit die Abfrage direkt verwendet werden kann?
Danke
Jeder macht Fehler - viele Fehler brauchen EDV!

TBug
Beiträge: 177
Registriert: Mi 2. Sep 2015, 11:09
OS, Lazarus, FPC: Lazaurus 2.2.4 FPC 3.2.2
CPU-Target: Windows 32/64bit

Re: SQLite Datumsabfragen

Beitrag von TBug »

Was für einen Typ besitzt denn das Tabellenfeld "Datum"?


.

Michl
Beiträge: 2505
Registriert: Di 19. Jun 2012, 12:54

Re: SQLite Datumsabfragen

Beitrag von Michl »

Wenn du Datum als Text (siehe https://www.sqlite.org/datatype3.html) deklariert hast, sollte es so funktionieren:

Code: Alles auswählen

    SqlQueryB.SQL.Text := 'SELECT DATE(Datum), Art, Betrag FROM tBuchung WHERE Datum >= :aDatum;';
    SqlQueryB.ParamByName('aDatum').AsString := '2015-01-01';

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection; 

RuhrPotto
Beiträge: 39
Registriert: Mi 6. Mai 2015, 12:52

Re: SQLite Datumsabfragen

Beitrag von RuhrPotto »

TBug hat geschrieben:Was für einen Typ besitzt denn das Tabellenfeld "Datum"?.


Das Feld ist definiert als

Code: Alles auswählen

'Datum         DATETIME, ' 
 
Ohne Formatierung ergibt sich folgende Darstellung IN der Konsole:
 
sqlite> SELECT Datum, Art, Betrag FROM tBuchung;
2457272.5|0|100
 


Speicherung daher wohl als REAL-Feld mit julanischem Datum. Wie erwähnt, funktioniert SqlQueryB.ParamByName('FIRST').AsDateTime := MFirst;; nicht jedoch ein direktes Datum.
Jeder macht Fehler - viele Fehler brauchen EDV!

Michl
Beiträge: 2505
Registriert: Di 19. Jun 2012, 12:54

Re: SQLite Datumsabfragen

Beitrag von Michl »

Dann sollte es doch so funktionieren:

Code: Alles auswählen

 SqlQueryB.SQL.Text := 'SELECT DATE(Datum), Art, Betrag FROM tBuchung WHERE Datum >= :aDatum;';
SqlQueryB.ParamByName('aDatum').AsDateTime := StrToDate('01.01.2015');

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection; 

Michl
Beiträge: 2505
Registriert: Di 19. Jun 2012, 12:54

Re: SQLite Datumsabfragen

Beitrag von Michl »

RuhrPotto hat geschrieben:Speicherung daher wohl als REAL-Feld mit julanischem Datum. Wie erwähnt, funktioniert SqlQueryB.ParamByName('FIRST').AsDateTime := MFirst;; nicht jedoch ein direktes Datum.
Das geht auch (habe es eben mal probiert), ob es besser ist, steht auf einem anderen Blatt:

Code: Alles auswählen

  Function GregorianToJulian(Year,Month,Day:Longint):LongInt;  //Kopiert aus Unit UnixUtil
  Var
    Century,XYear: LongInt;
  Const
    C1970=2440588;
    D0   =   1461;
    D1   = 146097;
    D2   =1721119;
  Begin
    If Month<=2 Then
     Begin
       Dec(Year);
       Inc(Month,12);
     End;
    Dec(Month,3);
    Century:=(longint(Year Div 100)*D1) shr 2;
    XYear:=(longint(Year Mod 100)*D0) shr 2;
    GregorianToJulian:=((((Month*153)+2) div 5)+Day)+D2+XYear+Century;
  End;
 
begin
    SQLQuery1.SQL.Text := 'SELECT DATE(datum) FROM testtable WHERE datum > ' + IntToStr(GregorianToJulian(2015, 01, 01)) + ';';
    SQLQuery1.Open;
end;

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection; 

RuhrPotto
Beiträge: 39
Registriert: Mi 6. Mai 2015, 12:52

Re: SQLite Datumsabfragen

Beitrag von RuhrPotto »

Ich brauch es aber - weil an der Stelle im Programm einfacher - in dieser Form:
SELECT DATE(Datum), Art, Betrag FROM tBuchung WHERE Datum >= '2015-01-01';

Die SQL wird generiert aus Usereingaben und die Anzahl der PARAMS ist unklar. Insofern ist die Verwendung von SqlQueryB.ParamByName .. nicht meine erste Wahl.
Jeder macht Fehler - viele Fehler brauchen EDV!

RuhrPotto
Beiträge: 39
Registriert: Mi 6. Mai 2015, 12:52

Re: SQLite Datumsabfragen

Beitrag von RuhrPotto »

:idea: Danke hab jetzt ne Lösung. Der Tip mit dem julianischem Datum hat mich weiter gebracht:

Code: Alles auswählen

'SELECT TOTAL(Betrag) FROM tBuchung WHERE Art = 0 '
         + 'AND Datum > julianday('+'''2015-01-01'''+')';   


Die Verwendung der SQLIte-Funktion julianday rechnet das Datum selber um und bringt jetzt die erwartete Ergebnismenge

Alternativ hat DATEUTILS auch die Funktion DateTimeToJulianDate

Trotzdem ein Hickhack
Jeder macht Fehler - viele Fehler brauchen EDV!

TBug
Beiträge: 177
Registriert: Mi 2. Sep 2015, 11:09
OS, Lazarus, FPC: Lazaurus 2.2.4 FPC 3.2.2
CPU-Target: Windows 32/64bit

Re: SQLite Datumsabfragen

Beitrag von TBug »

Wenn das Feld ein TDateTime, also ein Double ist, warum machst Du dann nicht einfach:

Code: Alles auswählen

 
lSql := 'SELECT TOTAL(Betrag) FROM tBuchung WHERE Art = 0 AND Datum > ' + StrToDateTime('24.11.2015');
 

Bei StrToDateTime kannst Du auch wahlweise verschiedene Datumsschreibweisen mit dem Parameter FormatSettings angeben.


.

Antworten