我有一个Sqlite表,如下所示称为余额历史记录:
表格平衡历史
Date Amount
2013-11-01 16:26:52 1000
2013-11-15 13:20:52 2000
2013-11-27 12:26:55 3000
我想计算一个月的平均值。
**
** 这将是(1000 * 14天+ 2000 * 12天+ 3000 * 4天)/ 30天 =(14000 + 24000 + 12000)/ 30 = 1666.67
我如何在SQlite中实现这一目标?任何帮助将不胜感激。
感谢
答案 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