2016-07-12 9 views
1

Sprich, ich habe die folgende Tabelle:SQLite-Abfrage für n-ten Tag des Monats

CREATE TABLE Data (
    Id INTEGER PRIMARY KEY, 
    Value DECIMAL, 
    Date DATE); 

Da die Anwendung ist finanzbezogenen, Benutzer kann wählen, an welchem ​​Tag der erste Tag des Monats sein würde. Zum Beispiel, wenn er jeden 10. des Monats Gehalt erhält, kann er den ersten Tag des Monats auf 10 setzen.

Ich möchte eine Abfrage erstellen, die Durchschnittswert für n-ten Tag des Monats zurückgibt, wie vom Benutzer definiert. Zum Beispiel:

Date   | Value 
---------------+------ 
10.01.2016  | 10 
11.01.2016  | 15 
10.02.2016  | 20 
11.03.2016  | 10 

Ergebnis der Abfrage sollte sein:

Day | Average 
----+-------- 
1 | 15 
2 | 12.5 

Beachten Sie, dass, wenn der Benutzer ersten Tag bis zum 10. setzt, 9. des Monats 28. sein können, 29., 30. oder 31. Tag ein Monat (abhängig davon, von welchem ​​Monat wir sprechen). Das ist also nicht so einfach wie das Extrahieren der Tagesnummer aus dem Datum.

+0

Ich kann mir vorstellen, dass dies haarig wird, weil verschiedene Monate eine andere Anzahl von Tagen haben. Und für einige Monate (z. B. Februar) variiert die Anzahl der Tage mit dem Jahr. –

Antwort

1

Unter der Annahme, dass die Datumswerte verwenden nicht das Format dd.mm.yyyy aber eines der supported date formats, können Sie die built-in date functions verwenden, um dies zu berechnen.

Um die Differenz in Tagen zwischen zwei Daten zu berechnen, konvertieren Sie sie in ein Datumsformat, das Tage als Zahl verwendet, d. H. Julianische Tage.

Um die ‚Basis‘ Tag für einen Monat zu bekommen, können wir Modifikatoren verwenden:

> SELECT julianday('2001-02-11') - 
     julianday('2001-02-11', 'start of month', '+10 days') + 2; 
2.0 

(Die +2 benötigt wird, weil wir zum 1. des Monats hinzufügen, nicht die 0-ten, und wir zählen beginnt bei 1, nicht 0)

Wenn der Tag vor dem zehnten wird, würde der berechnete Wert Null oder negativ werden, und wir haben den vorherigen Monat verwenden, anstatt:

> SELECT julianday('2001-02-09') - 
     julianday('2001-02-09', 'start of month', '-1 month', '+10 days') + 2; 
31.0 

C ombining diese Ergebnisse in diesem Ausdruck die n für ein Datum Date zu berechnen: can

CASE 
WHEN julianday(Date) - 
    julianday(Date, 'start of month', '+10 days') + 2 > 0 
THEN julianday(Date) - 
    julianday(Date, 'start of month', '+10 days') + 2 
ELSE julianday(Date) - 
    julianday(Date, 'start of month', '-1 month', '+10 days') + 2 
END 

Sie die diese Verwendung in Ihrer Suchanfrage:

SELECT CASE...END AS Day, 
     AVG(Value) AS Average 
FROM Data 
GROUP BY Day; 
0

Scheint, wie ich parallel eine andere Lösung gefunden:

SELECT avg(Amount), 
     strftime("%d", Date, "-9 days") AS day 
FROM (
    SELECT sum(Amount) AS Amount, 
     strftime("%Y-%m-%d", Date, "start of day") AS Date 
    FROM Operations 
    GROUP BY strftime("%Y-%m-%d", Date, "start of day") 
) 
GROUP BY day; 

Wo "-9 Tage" für den 10. des Monats ist (so first_day-1).