Tage Datumsbereich Plus und Minus bei Select von SQLITE angeben

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
Benutzeravatar
martinjo
User
Beiträge: 186
Registriert: Dienstag 14. Juni 2011, 20:03

Hallo,

mich interessiert, warum folgendes Platzhalter nicht ersetzt werden:
query = "SELECT * FROM postbank_complete WHERE date BETWEEN date(?, '-? day') AND date(?, '+? day')"

Wenn ich es ausführe, kommt immer die Meldung, dass nur 2 Platzhalter gefunden werden.

Klar, kann ich die Tage auch manuell ausrechnen.

MfG
BlackJack

@martinjo: Na da sind insgesamt nur zwei Platzhalter drin. Du fragst Dich doch auch nicht warum bei ``a = 42; print "a"`` ein 'a' und nicht 42 ausgegeben wird. Die Platzhalter sind für Werte in der SQL-Anweisung, und Du willst da keinen SQL-Wert hinein formatieren, sondern etwas in ein Zeichenkettenliteral in der SQL-Anweisung. Was ginge wäre ``…BETWEEN date(?, ?)…`` und dann für das zweite Fragezeichen ``'-{0} day'.format(x)`` als Wert einzusetzen. Oder aber die ±x Tage tatsächlich auf Python-Seite auszurechnen. Das geht mit `datetime`-Objekten ja problemlos.
Benutzeravatar
martinjo
User
Beiträge: 186
Registriert: Dienstag 14. Juni 2011, 20:03

Danke

Na da sind insgesamt nur zwei Platzhalter drin
Irgendwie war dass bei mit noch nicht ganz drin, dass Werte in Klammer in diesem "String-Befehl" nicht ersetzt werden.

Was ginge wäre ``…BETWEEN date(?, ?)…`` und dann für das zweite Fragezeichen ``'-{0} day'.format(x)`` als Wert einzusetzen.
Danke für den Tipp

Oder aber die ±x Tage tatsächlich auf Python-Seite auszurechnen. Das geht mit `datetime`-Objekten ja problemlos.
So habe ich das nun auch verwirklicht:

Code: Alles auswählen

        (year, month, day) = self.from_date_calendar.get_date()
        from_date = datetime.datetime(year=year, month=month+1, day=day)
        from_date = from_date - datetime.timedelta(ADDITIONAL_PAYMENT_RANGE[0])
        from_date = from_date.strftime("%Y-%m-%d") 
        logger.debug("from_date = {}".format(from_date))
            
        (year, month, day) = self.to_date_calendar.get_date()
        to_date = datetime.datetime(year=year, month=month+1, day=day)    
        to_date = to_date + datetime.timedelta(ADDITIONAL_PAYMENT_RANGE[1])
        to_date = to_date.strftime("%Y-%m-%d") 
        logger.debug("to_date = {}".format(to_da
te))
BlackJack

@martinjo: Ich bin ein bisschen von den Datentypen verwundert. Warum gibt die `get_date()`-Methode kein `datetime.date`-Objekt zurück? Warum ist ADDITIONAL_PAYMENT_RANGE[0] nicht bereits ein `timedelta`-Objekt? Bei negativen Fall am besten auch schon mit Vorzeichen. Warum wird `from_date` dann wieder in eine Zeichenkette umgewandelt?

Ist der `logger` selbst geschrieben oder verwendest Du das `logging`-Modul? Da würde ich die Zeichenkette dann nämlich nicht formatieren sondern das als ``debug('from_date = %s', from_date)`` schreiben. Dann wird die Formatierung nämlich vom Logger gemacht, und das nur falls es nötig ist.
Benutzeravatar
martinjo
User
Beiträge: 186
Registriert: Dienstag 14. Juni 2011, 20:03

@BlackJack
BlackJack hat geschrieben:Ich bin ein bisschen von den Datentypen verwundert. Warum gibt die `get_date()`-Methode kein `datetime.date`-Objekt zurück?
Wäre mir auch lieber. http://www.pygtk.org/pygtk2reference/cl ... --get-date
BlackJack hat geschrieben:Warum ist ADDITIONAL_PAYMENT_RANGE[0] nicht bereits ein `timedelta`-Objekt?
Bisher waren die Werte fest im Skript. Nun habe ich am Anfang des Skriptes einfach eine Liste hinzugefügt wo ich die Werte eintrage. Geplant war ja ursprünglich, "+ ? days". Ist noch im Aufbau :-)
BlackJack hat geschrieben:Warum wird `from_date` dann wieder in eine Zeichenkette umgewandelt?
Für den SQL Befehl. In diesem Format ist das Datum in den SQLite Tabellen gespeichert. Habe ich anders nicht hin bekommen.

Code: Alles auswählen

Ist der `logger` selbst geschrieben oder verwendest Du das `logging`-Modul? Da würde ich die Zeichenkette dann nämlich nicht formatieren sondern das als ``debug('from_date = %s', from_date)`` schreiben. Dann wird die Formatierung nämlich vom Logger gemacht, und das nur falls es nötig ist.
Ich verwende das `logging`-Modul. Danke, war mir noch nicht bekannt. Ich habe noch nicht mal alle print-Befehle durch logging ersetzt. Jetzt muss ich die wieder alle anpassen, verdammt :oops:
Wie meinst du denn dass mit: "und das nur falls es nötig ist" ?
BlackJack

@martinjo: In der Datenbank ist das Datum doch hoffentlich als `DATE` gespeichert und nicht als `TEXT` oder ähnliches‽ Da kann man das Datumsobjekt übergeben:

Code: Alles auswählen

In [62]: cur.execute('SELECT date(?, "-2 day")', [Date.today()]).fetchall()
Out[62]: [(u'2016-04-15',)]
Nicht nötig ist die Formatierung wenn das Log-Level so gesetzt ist das die Verwendung nicht erfolgt. DEBUG ist ja zum Beispiel normalerweise nicht die normale Stufe die man bei einem Produktivsystem normalerweise aktiviert, sondern erst/nur wenn man auf Fehlersuche ist.
Benutzeravatar
martinjo
User
Beiträge: 186
Registriert: Dienstag 14. Juni 2011, 20:03

BlackJack hat geschrieben:In der Datenbank ist das Datum doch hoffentlich als `DATE` gespeichert und nicht als `TEXT` oder ähnliches‽
Habe ich mir als TODO notiert. Danke. Ich hatte damals geglaubt, dass ich mit sqlite dies nicht speichern, kann. Gerade geschaut, finde ich wirklich nicht hier: https://docs.python.org/2/library/sqlit ... thon-types

Oder dann einfach als int wie hier gezeigt?:
http://pythoncentral.io/advanced-sqlite ... in-python/
BlackJack

¹martinjo: Das steht in der Dokumentation ein kleines Stück weiter unten: https://docs.python.org/2/library/sqlit ... converters (und auch auf der anderen von Dir verlinkten Seite).
Benutzeravatar
martinjo
User
Beiträge: 186
Registriert: Dienstag 14. Juni 2011, 20:03

Thx
Antworten