【问题标题】:Get a count of records created each week in SQL获取 SQL 中每周创建的记录数
【发布时间】:2015-03-01 20:42:20
【问题描述】:

我有一张桌子问题。如何计算一周内提出的所有问题?

更笼统地说,我如何按记录的创建周存储记录?

Questions
id     created_at            title            
----------------------------------------------------
1      2014-12-31 09:43:42   "Add things"
2      2013-11-23 02:98:55   "How do I ruby?"
3      2015-01-15 15:11:19   "How do I python?"
...

我正在使用 SQLLite,但 PG 答案也很好。

或者,如果您有使用 Rails ActiveRecord 的答案,那就太棒了,但不是必需的。

我一直在尝试使用 DATEPART() 但还没有成功:http://msdn.microsoft.com/en-us/library/ms174420.aspx

【问题讨论】:

  • 请定义“周”。您是指 ISO 8601 定义(周一 - 周日)吗?你想把多年的几个星期混在一起吗?一年的第一周包含 1 月 4 日 (ISO 8601)? DATEPART(),以及您的链接是针对属于 SQL Server 的 tSQL 的。不适用于 SQLite 或 Postgres。

标签: sql ruby-on-rails sqlite postgresql rails-activerecord


【解决方案1】:

在 postgreSQL 中很简单:

SELECT id, created_at, title, date_trunc('week', created_at) created_week
  FROM Questions

如果您想获得每周的问题数,只需执行以下操作:

SELECT date_trunc('week', created_at) created_week, COUNT(*) weekly_cnt
  FROM Questions
 GROUP BY date_trunc('week', created_at)

希望这会有所帮助。请注意,date_trunc() 将返回日期而不是数字(即,它不会返回一年中星期几的序数)。

更新:

此外,如果您想在单个查询中完成这两项操作,您可以按以下方式进行:

SELECT id, created_at, title, date_trunc('week', created_at) created_week
     , COUNT(*) OVER ( PARTITION BY date_trunc('week', created_at) ) weekly_cnt
  FROM Questions

在上述查询中,我使用COUNT(*) 作为窗口函数并按创建问题的那一周进行分区。

【讨论】:

    【解决方案2】:

    如果created_at 字段已经被索引,我会简单地查找所有在X 和Y 之间具有created_at 值的行。这样就可以使用索引了。

    例如,要在 2015 年的第 3 周获取具有 created_at 值的行,您可以运行:

    select *
      from questions
     where created_at between '2015-01-11' and '2015-01-17'
    

    这将允许使用索引。

    如果您希望能够在 where 子句中指定一周,您可以使用 date_partextract 函数在此表中添加一列存储年份和周#,然后对该列进行索引,以便查询可以利用它。

    如果您不想添加列,当然可以在 where 子句中使用任一函数并查询表,但您将无法利用任何索引。

    因为您提到不想在表中添加列,所以我建议添加基于函数的索引。

    例如,如果您的 ddl 是:

    create table questions
    (
      id int,
      created_at timestamp,
      title varchar(20)
    );
    
    insert into questions values
    (1, '2014-12-31 09:43:42','"Add things"'),
    (2, '2013-11-23 02:48:55','"How do I ruby?"'),
    (3, '2015-01-15 15:11:19','"How do I python?"');
    
    
    create or replace function to_week(ts timestamp)
       returns text
       as 'select concat(extract(year from ts),extract(week from ts))'
       language sql
       immutable
       returns null on null input;
    
    create index week_idx on questions (to_week(created_at));
    

    你可以跑:

    select q.*, to_week(created_at) as week
      from questions q
     where to_week(created_at) = '20153';
    

    得到:

    | ID |                     CREATED_AT |              TITLE |  WEEK |
    |----|--------------------------------|--------------------|-------|
    |  3 | January, 15 2015 15:11:19+0000 | "How do I python?" | 20153 |
    

    (反映2015年第三周,即'20153'

    小提琴: http://sqlfiddle.com/#!15/c77cd/3/0

    你可以类似地运行:

    select q.*,
           concat(extract(year from created_at), extract(week from created_at)) as week
      from questions q
     where concat(extract(year from created_at), extract(week from created_at)) =
           '20153';
    

    小提琴: http://sqlfiddle.com/#!15/18c1e/3/0

    但它不会利用基于函数的索引,因为没有。此外,它不会使用您在created_at 字段上可能拥有的任何索引,因为虽然该字段可能已被索引,但您实际上并没有在该字段上进行搜索。您正在搜索针对该字段应用的函数的结果。所以不能使用列本身的索引。

    如果表很大,您将需要基于函数的索引或包含该周且本身已编入索引的列。

    【讨论】:

      【解决方案3】:

      SQLite 没有像 MS SQL Server 那样的原生日期时间类型,因此答案可能取决于您存储日期的方式。并非所有 T-SQL 都可以在 SQLite 中运行。

      您可以将 datetime 存储为从 1970 年 1 月 1 日凌晨 12:00 开始计算秒数的整数。一周有 604,800 秒。所以你可以查询像

      这样的表达式
      rawdatetime / 604800 -- iff rawdatetime is integer
      

      更多关于在 SQLite 中处理日期时间的信息:https://www.sqlite.org/datatype3.html

      【讨论】:

        【解决方案4】:

        使用strfdate(%V) 获取周数 将其存储在数据库中,并使用它来确定在哪一周提出问题

        http://apidock.com/ruby/DateTime/strftime

        SQL 也可以使用 DATE_FORMAT(datetime,'%u')

        所以使用:

        SELECT DATE_FORMAT(column,'%u') FROM Table
        

        【讨论】:

        • 这是可能的,但我不需要为这种查询创建任何中间表或额外的列。
        猜你喜欢
        • 2019-03-18
        • 2015-01-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-11-18
        • 2012-05-15
        • 1970-01-01
        相关资源
        最近更新 更多