每月第 n 天的 SQLite 查询

SQLite query for n-th day of month

说,我有以下 table:

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

由于该应用程序与财务相关,因此用户可以选择哪一天是该月的第一天。比如他每个月10号发工资,他可以把这个月的第一天设为10号。

我想创建一个查询,returns 用户定义的每月第 n 天的平均值。例如:

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

查询结果应该是:

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

请注意,如果用户将第一天设置为 10 号,则该月的 9 号可能是该月的 28 号、29 号、30 号或 31 号(取决于我们谈论的月份)。所以这不像从日期中提取天数那么简单。

假设日期值不使用 dd.mm.yyyy 格式,而是使用 supported date formats, you can use the built-in date functions 格式之一来计算。

要计算两个日期之间的天数差异,请将它们转换为使用天数作为数字的日期格式,即儒略日。

要获得一个月的 'base' 天,我们可以使用修饰符:

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

+2 是必需的,因为我们添加到月份的 1 号,而不是 0 号,并且我们从 1 开始计数,而不是 0。)

如果当天在十号之前,计算值将变为零或负数,我们必须使用上个月来代替:

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

在这个表达式中结合这些结果来计算日期 Date:

n
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

您可以在查询中使用它:

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

好像我同时找到了一个不同的解决方案:

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;

其中“-9 天”表示每月 10 日(因此 first_day-1)。