获取每周在SQL中创建的记录数
我有一张桌子,上面有问题。如何计算一周内提出的所有问题 更一般地说,如何在创建记录的一周内保存记录获取每周在SQL中创建的记录数,sql,ruby-on-rails,sqlite,postgresql,rails-activerecord,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
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(),但还没有找到任何成功的方法:使用strfdate(%V)获取周数。 将其存储在DB中,并使用它来确定问题是在哪一周提出的 SQL也可以使用DATE_格式(datetime,“%u”)执行此操作 因此,请使用:
SELECT DATE_FORMAT(column,'%u') FROM Table
SQLite不像MS SQL Server那样具有本机日期时间类型,因此答案可能取决于存储日期的方式。并非所有的T-SQL都能在SQLite中工作 您可以将datetime存储为一个整数,该整数从1970年1月1日凌晨12:00开始计算秒数。一周有604800秒。所以你可以查询一个表达式,比如
rawdatetime / 604800 -- iff rawdatetime is integer
有关在SQLite中处理日期时间的更多信息,请参见此处:如果在处创建的
字段已被索引,我只需查找所有在
处创建的值在X和Y之间的行。这样就可以使用索引
例如,要获取在2015年第3周创建了值为
的行,您可以运行:
select *
from questions
where created_at between '2015-01-11' and '2015-01-17'
这将允许使用索引
如果希望能够在where子句中指定一周,可以使用date\u部分
或extract
函数向该表添加一列,存储年和周,然后对该列编制索引,以便查询可以利用该列
如果不想添加列,当然可以使用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”
)
小提琴:
您可以类似地运行:
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';
小提琴:
但它不会利用基于函数的索引,因为没有。此外,它不会使用您在created\u at
字段上可能有的任何索引,因为虽然该字段可能被索引,但您实际上没有在该字段上搜索。您正在搜索针对该字段应用的函数的结果。因此,无法使用列本身上的索引
如果表很大,您可能需要一个基于函数的索引,或者需要一个包含该周的列,该列本身已被索引。在postgreSQL中,它很简单,如下所示:
SELECT id, created_at, title, date_trunc('week', created_at) created_week
FROM Questions
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
如果你想每周获得#个问题,只需执行以下操作:
SELECT date_trunc('week', created_at) created_week, COUNT(*) weekly_cnt
FROM Questions
GROUP BY date_trunc('week', created_at)
希望这有帮助。请注意,date\u trunc()
将返回日期而不是数字(即,它不会返回一年中一周的序号)
更新:
此外,如果您想在一个查询中同时完成这两个任务,可以按如下方式执行:
SELECT id, created_at, title, date_trunc('week', created_at) created_week
FROM Questions
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(*)
作为窗口函数,并按创建问题的周进行分区。这是可能的,但我不需要为此类查询创建任何中间表或额外列。请定义“周”。你是指ISO 8601定义(周一至周日)?你想把几周的时间和多年的时间混在一起吗?一年的第一周包含1月4日(ISO 8601)<代码>日期部分(),以及您的链接都是针对属于SQL Server的tSQL的。不适用于SQLite或Postgres。