获取每周在SQL中创建的记录数

时间:2015-01-03 22:54:10

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

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

更一般地说,如何在创建它们的那一周之前将记录存储起来?

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

4 个答案:

答案 0 :(得分:4)

在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(*)作为窗口函数,并按创建问题的那一周进行分区。

答案 1 :(得分:1)

如果已将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字段上可能包含的任何索引,因为虽然该字段可能已编入索引,但您实际上并未搜索该字段。您正在搜索针对该字段应用的函数的结果。因此不能使用列本身的索引。

如果表格很大,您将需要一个基于函数的索引或一个持有该周本身索引的列。

答案 2 :(得分:0)

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

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

SQL也可以使用DATE_FORMAT(日期时间,&#39;%u&#39;)

所以使用:

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

答案 3 :(得分:0)

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

您可以将日期时间存储为一个整数,该整数计算自1970年1月1日上午12:00起的秒数。一周有604,800秒。所以你可以查询像

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

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