【问题标题】:SQLite query to join on a range of dates?SQLite 查询加入一系列日期?
【发布时间】:2010-01-11 21:18:37
【问题描述】:

我正在使用 SQLite。

假设我有一张表 sales 有两列,datecount,以跟踪我在那个日期卖出了多少杯柠檬水。如果我在某一天不卖任何柠檬水,我会很沮丧,无法在 sales 表中创建新行。

我想了解在给定日期范围内售出的眼镜的平均数量。我可以发出这样的查询:

SELECT AVG(count) FROM sales WHERE date IS BETWEEN '2010-01-04' AND '2010-01-10';

但是,除非该范围内的所有日期都包含在表格中,否则结果将不准确。我需要一些方法来告诉 SQLite 将丢失的行计数为零。

我想如果我可以在某个日期范围内加入销售表,那将是理想的选择。这似乎是不可能的,因此从日期范围创建表格的简单方法可能是下一个最好的方法。我不想修改销售表,这对于柠檬水摊来说似乎很愚蠢,但在现实生活中更有意义。

正如我上面所说,我使用的是 SQLite,所以如果您向我推荐其他数据库,您将无济于事。也就是说,如果您对另一个数据库有更多经验并认为您的解决方案可以用普通 SQL 完成,我很乐意听到。

【问题讨论】:

  • 你能谈谈范围吗?它应该是任意长度吗?还是有最大值?

标签: sql datetime sqlite


【解决方案1】:

创建一个日历表并加入其中:

这样就可以了:

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);

【讨论】:

    【解决方案2】:

    我认为你需要这样的东西:

    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.

    【讨论】:

    • 聪明!我在想一些太复杂的事情。
    • 这很好,但它只适用于计算平均值。我还有一些更复杂的事情想做,但还不够。
    【解决方案3】:

    您可以使用递归公用表表达式来生成一系列日期并加入它:

    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/

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-10-13
      • 1970-01-01
      • 2016-09-11
      • 2013-10-17
      • 2019-10-14
      • 1970-01-01
      相关资源
      最近更新 更多