计算SQlite中月份的平均值

时间:2013-11-25 10:50:11

标签: sqlite

我有一个Sqlite表,如下所示称为余额历史记录:

表格平衡历史

Date                  Amount
2013-11-01 16:26:52   1000
2013-11-15 13:20:52   2000
2013-11-27 12:26:55   3000

我想计算一个月的平均值。

**

  • 预期OutPut将为1666.67

** 这将是(1000 * 14天+ 2000 * 12天+ 3000 * 4天)/ 30天 =(14000 + 24000 + 12000)/ 30 = 1666.67

我如何在SQlite中实现这一目标?任何帮助将不胜感激。

感谢

1 个答案:

答案 0 :(得分:0)

首先,我们必须计算每个间隔的开始和结束。

简单查询(SELECT Date AS "From", Amount FROM BalanceHistory WHERE Date GLOB '2013-11*')获取该月中每个时间间隔的开头。 (GLOB区分大小写,因此允许使用普通索引; LIKE需要特殊的不区分大小写的索引。)

如果该月的第一天没有记录,则UNION ALL之后的部分会添加上个月的最后一条记录,并将该日期更改为第1天。

COALESCE计算间隔的结束。 子查询从表中获取下一个日期(如果当前月份中有一个日期)。 如果没有这样的记录,则需要在下个月的第一天:

SELECT date("From") AS "From",
       COALESCE((SELECT date(MIN(Date))
                 FROM BalanceHistory
                 WHERE Date > "From"
                   AND Date GLOB '2013-11*'),
                date('2013-11-01', '+1 month')
               ) AS "To",
       "Amount"
FROM (SELECT Date AS "From",
             Amount
      FROM BalanceHistory
      WHERE Date GLOB '2013-11*'
      UNION ALL
      SELECT *
      FROM (SELECT date(Date, '+1 month', 'start of month'),
                   Amount
            FROM BalanceHistory
            WHERE Date < '2013-11'
              AND NOT EXISTS (SELECT 1
                              FROM BalanceHistory
                              WHERE Date GLOB '2013-11-01*')
            ORDER BY Date DESC
            LIMIT 1)
     );
From        To          Amount    
----------  ----------  ------
2013-11-01  2013-11-15  1000
2013-11-15  2013-11-27  2000
2013-11-27  2013-12-01  3000

然后我们可以将其包装在另一个查询中以计算天数,并将它们相加。 strftime计算该月的最后一天,即天数:

SELECT SUM((julianday("To") - julianday("From")) * Amount) /
       strftime('%d', '2013-11-01', '+1 month', '-1 day') AS MonthAvg
FROM (SELECT date("From") AS "From",
             COALESCE((SELECT date(MIN(Date))
                       FROM BalanceHistory
                       WHERE Date > "From"
                         AND Date GLOB '2013-11*'),
                      date('2013-11-01', '+1 month')
                     ) AS "To",
             "Amount"
      FROM (SELECT Date AS "From",
                   Amount
            FROM BalanceHistory
            WHERE Date GLOB '2013-11*'
            UNION ALL
            SELECT *
            FROM (SELECT date(Date, '+1 month', 'start of month'),
                         Amount
                  FROM BalanceHistory
                  WHERE Date < '2013-11'
                    AND NOT EXISTS (SELECT 1
                                    FROM BalanceHistory
                                    WHERE Date GLOB '2013-11-01*')
                  ORDER BY Date DESC
                  LIMIT 1)
           )
     )

虽然我们正在使用它,但我们可以将其包装在另一个查询中,将所有这些2013-11字符串替换为从表中读取的月份。 这允许每个月计算一次:

SELECT Month,
       (SELECT SUM((julianday("To") - julianday("From")) * Amount) /
               strftime('%d', Month || '-01', '+1 month', '-1 day')
        FROM (SELECT date("From") AS "From",
                     COALESCE((SELECT date(MIN(Date))
                               FROM BalanceHistory
                               WHERE Date > "From"
                                 AND Date GLOB Month || '*'),
                              date(Month || '-01', '+1 month')
                             ) AS "To",
                     "Amount"
              FROM (SELECT Date AS "From",
                           Amount
                    FROM BalanceHistory
                    WHERE Date GLOB Month || '*'
                    UNION ALL
                    SELECT *
                    FROM (SELECT date(Date, '+1 month', 'start of month'),
                                 Amount
                          FROM BalanceHistory
                          WHERE Date < Month
                            AND NOT EXISTS (SELECT 1
                                            FROM BalanceHistory
                                            WHERE Date GLOB Month || '-01*')
                          ORDER BY Date DESC
                          LIMIT 1)
                   )
             )
       ) AS MonthAvg
FROM (SELECT DISTINCT strftime('%Y-%m', Date) AS Month
      FROM BalanceHistory)
ORDER BY 1