我正在使用SQLite。
假设我有一个表sales
,其中包含两列date
和count
,以跟踪我在该日期销售的柠檬水的数量。如果我在某一天没有出售任何柠檬水,我很郁闷,无法在sales
表中创建新行。
我想知道在给定日期范围内销售的平均眼镜数量。我可以发出这样的查询:
SELECT AVG(count) FROM sales WHERE date IS BETWEEN '2010-01-04' AND '2010-01-10';
但是,除非表格中包含该范围内的所有日期,否则结果将不准确。我需要一些方法告诉SQLite将丢失的行计为零。
我想如果我能加入日期范围的销售表,那将是理想的。这似乎不太可能,因此从日期范围创建表的简单方法可能是下一个最好的方法。我不想修改销售表,这对于柠檬水摊来说似乎很傻,但在现实生活中更有意义。
正如我上面所说,我正在使用SQLite,所以如果你向我推荐其他数据库,你就没有帮助。也就是说,如果您对其他数据库有更多经验,并认为您的解决方案可以在vanilla SQL中完成,我很乐意听到它。
答案 0 :(得分:6)
创建一个日历表并加入其中:
这样的事情会:
create table dates (id integer primary key);
insert into dates default values;
insert into dates default values;
insert into dates select null from dates d1, dates d2, dates d3 , dates d4;
insert into dates select null from dates d1, dates d2, dates d3 , dates d4;
alter table dates add date datetime;
update dates set date=date('2000-01-01',(-1+id)||' day');
这将覆盖你到2287-05-20 在日期表中向日期列添加索引不会有害。我的sqlite有点生疏,所以我建议你就此问the manual。
编辑:索引代码:
create unique index ux_dates_date on dates (date);
答案 1 :(得分:3)
我认为你需要这样的东西:
SELECT sum(count) / ((strftime('%s','2010-01-10')-strftime('%s','2010-01-04')+86400)/86400)
FROM sales
WHERE date IS BETWEEN '2010-01-04' AND '2010-01-10';
查询通过获取给定日期之间的秒数来计算确切的天数 除以86400(= 24 * 3600)秒。
例如
SELECT (strftime('%s','2010-03-01')-strftime('%s','2010-01-01') + 86400) / 86400
输出60
这是正确的值。
查看SQLite的Date And Time Functions.
答案 2 :(得分:1)
您可以使用递归公用表表达式生成一系列日期并加入其中:
WITH RECURSIVE
cnt(x) AS (
SELECT 0
UNION ALL
SELECT x+1 FROM cnt
LIMIT (SELECT ((julianday('2010-01-10') - julianday('2010-01-04'))) + 1)
),
WITH date_series AS (
SELECT date(julianday('2010-01-04'), '+' || x || ' days') as date
FROM date_series ds
)
SELECT AVG(COALESCE(s.count, 0)) as avg_sales_count
FROM date_series ds
LEFT JOIN sales s ON ds.date = s.date
我在这里写了一篇博文,其中包含更多信息:http://www.geekytidbits.com/generate-date-range-sqlite/