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

Get a count of records created each week in SQL

我有一个table问题。我如何统计一周内提出的所有问题?

更一般地说,我如何按创建记录的周对记录进行分类?

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

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

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

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

所以使用:

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

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

您可以将日期时间存储为从 1/1/1970 12:00 AM 开始计算秒数的整数。一周有 604,800 秒。所以你可以查询像

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

更多关于在 SQL 网站上处理日期时间的信息:https://www.sqlite.org/datatype3.html

如果 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 函数向此 table 添加一列来存储年份和 week #,然后索引该列以便查询可以利用它。

如果您不想添加该列,您当然可以在 where 子句中使用任一函数并针对 table 进行查询,但您将无法利用任何索引.

因为您提到不想向 table 添加列,我建议添加基于函数的索引。

例如,如果您的 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'

Fiddle: 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';

Fiddle: http://sqlfiddle.com/#!15/18c1e/3/0

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

如果 table 很大,您将需要一个基于函数的索引或一个包含该周的列,该列本身已被索引。

在 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() 将 return 一个日期而不是一个数字(即,它不会 return 一年中的第几周的序数)。

更新:

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

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(*) 用作 window 函数并按创建问题的周进行分区。