【问题标题】:How do I GROUP BY on every given increment of a field value?如何对字段值的每个给定增量进行 GROUP BY?
【发布时间】:2010-10-25 23:03:22
【问题描述】:

我有一个 Python 应用程序。它有一个 SQLite 数据库,里面充满了关于发生的事情的数据,由网络爬虫从网络上检索。该数据在为它们保留的列中包括时间-日期组,作为 Unix 时间戳。我想检索做某事的组织的名称并计算他们做这些事情的频率,但要每周执行一次(即 604,800 秒),我有数据。

伪代码:

for each 604800-second increment in time:
 select count(time), org from table group by org

基本上我要做的是像在时间列上排序的列表一样遍历数据库,步长值为 604800。目的是分析不同组织在总数中的分布如何随时间变化。

如果可能的话,我想避免从数据库中提取所有行并在 Python 中处理它们,因为这似乎 a) 效率低下,并且 b) 考虑到数据在数据库中,这可能毫无意义。

【问题讨论】:

    标签: python sql sqlite iteration increment


    【解决方案1】:

    不熟悉 SQLite 我认为这种方法应该适用于大多数数据库,因为它会找到周数并减去偏移量

    SELECT org, ROUND(time/604800) - week_offset, COUNT(*)
    FROM table
    GROUP BY org, ROUND(time/604800) - week_offset
    

    在 Oracle 中,如果时间是日期列,我将使用以下内容:

    SELECT org, TO_CHAR(time, 'YYYY-IW'), COUNT(*)
    FROM table
    GROUP BY org, TO_CHAR(time, 'YYYY-IW')
    

    SQLite 可能具有类似的功能,允许这种更易于使用的 SELECT。

    【讨论】:

    • 是的,您可以使用 strftime 函数来格式化日期时间字符串(以及 unixepoch 修饰符,如果这是您开始的),以及基于截断 unix-epoch 编号的更简单方法.
    • 谢谢!这就是解决方案; SQLite 中不存在 TO_CHAR,但 strftime 函数存在,我能够以这种方式对其进行排序。
    【解决方案2】:

    创建一个表格,列出自纪元以来的所有星期,并将 JOIN 它添加到您的事件表中。

    CREATE TABLE Weeks (
      week INTEGER PRIMARY KEY
    );
    
    INSERT INTO Weeks (week) VALUES (200919); -- e.g. this week
    
    SELECT w.week, e.org, COUNT(*)
    FROM Events e JOIN Weeks w ON (w.week = strftime('%Y%W', e.time))
    GROUP BY w.week, e.org;
    

    每年只有 52-53 周。即使您将 Weeks 表填充 100 年,它仍然是一个小表。

    【讨论】:

      【解决方案3】:

      要以基于集合的方式(这是 SQL 擅长的方式)执行此操作,您将需要基于集合的时间增量表示。这可以是临时表、永久表或派生表(即子查询)。我对 SQLite 不太熟悉,自从我使用 UNIX 以来已经有一段时间了。 UNIX 中的时间戳距离某个设置的日期/时间仅 # 秒?使用标准日历表(在数据库中很有用)...

      SELECT
           C1.start_time,
           C2.end_time,
           T.org,
           COUNT(time)
      FROM
           Calendar C1
      INNER JOIN Calendar C2 ON
           C2.start_time = DATEADD(dy, 6, C1.start_time)
      INNER JOIN My_Table T ON
           T.time BETWEEN C1.start_time AND C2.end_time  -- You'll need to convert to timestamp here
      WHERE
           DATEPART(dw, C1.start_time) = 1 AND    -- Basically, only get dates that are a Sunday or whatever other day starts your intervals
           C1.start_time BETWEEN @start_range_date AND @end_range_date  -- Period for which you're running the report
      GROUP BY
           C1.start_time,
           C2.end_time,
           T.org
      

      日历表可以采用您想要的任何形式,因此您可以在其中使用 UNIX 时间戳作为 start_time 和 end_time。您只需使用您可能想要使用的任何可能范围内的所有日期预先填充它。即使从 1900-01-01 到 9999-12-31 也不会是一张非常大的桌子。对于很多报告类型的查询,它可以派上用场。

      最后,这段代码是 T-SQL,因此您可能需要将 DATEPART 和 DATEADD 转换为 SQLite 中的任何等效项。

      【讨论】:

        猜你喜欢
        • 2014-08-21
        • 2017-09-12
        • 2011-05-25
        • 2017-12-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多