使用选定时间段从数据库中的一列或两列中计算大量内容的有效方法

Posted

技术标签:

【中文标题】使用选定时间段从数据库中的一列或两列中计算大量内容的有效方法【英文标题】:Efficient way of counting a large content from a cloumn or a two in a database using selected time period 【发布时间】:2013-08-21 21:45:23 【问题描述】:

我需要列出在所选时间段内(自请求列表之日起)已添加到数据库的 column1 数量 - 每天、每周(过去 7 天)、每月(过去 30 天)和每季度(过去 3 个月)。例如,下面是我为执行此任务而创建的表。

      Column      |            Type             |                      Modifiers
------------------+-----------------------------+-----------------------------------------------------
column1            character varying (256)        not null default nextval
date               timestamp without time zone    not null default now()
coloumn2           charater varying(256)          ..........

现在,我需要 column1 中相对于所选时间段的条目总数。 喜欢,

     Column 1     |            Date             |           Coloumn2
------------------+-----------------------------+-----------------------------------------------------
abcdef              2013-05-12 23:03:22.995562    122345rehr566
njhkepr             2013-04-10 21:03:22.337654    45hgjtron
ffb3a36dce315a7     2013-06-14 07:34:59.477735    jkkionmlopp
abcdefgggg          2013-05-12 23:03:22.788888    22345rehr566

根据上述数据,对于每天选择的时间段,它应该是 count= 2

我试过做这个查询

select count(column1) from table1 where date='2012-05-12 23:03:22';

并获得与时间戳匹配的确切记录。但我真的需要以正确的方式来做,我相信这不是检索计数的有效方法。任何可以帮助我了解编写此类查询的正确有效方式的人都会很棒。我是数据库世界的新手,我正在努力提高编写任何查询的效率。 谢谢! [编辑] 当前每个查询都需要 175854 毫秒来处理。什么是减少相应处理时间的有效方法。 任何帮助都会非常棒。我正在使用 Postgresql 来做同样的事情。

【问题讨论】:

column1有什么意义?你不只是想要“行数”吗?或者您想要该时间段内第 1 列中不同值的数量? Coloumn1 是唯一的,我需要取决于所选时间段的行数或数据数,例如,如果我想获得过去 7 天(每周)的数据,我应该得到总数从今天起在该时间段内列 1 中的数据。 由于数据库太大了,我需要做一个高效的查询,目前处理查询需要175854ms。因此,我很好奇,是否有任何有效的方法可以做到这一点并进行一些优化? 再说一次,你为什么要在 column1 上喋喋不休?您所说的没有任何内容表明 column1 的内容以任何方式相关。是或否:您想要过去 7 天内的 行数 吗? 表中很少有其他列是/可能留空或空,这取决于一些后端逻辑来相应地填充它,第 1 列也可能如此。因此,我不需要在特定时间段内使用任何列的表中的总行数(因为它会有所不同)。我打算只检索选定时间段(每周、每天、每月等)的第 1 列内容的计数。希望我回答了,我也会将其添加到问题中。 【参考方案1】:

为了提高效率,条件应该比较理智类型的值作为被比较的列。在这种情况下,被比较的列 - Date - 具有 timestamp 类型,因此我们需要使用 tinestamp 值的范围。

与此保持一致,您应该使用current_timestamp 作为“现在”值,并由documentation 确认,从timestamp 中减去interval 会得到timestamp,所以...

过去 1 天:

select count(*) from table1
where "Date" > current_timestamp - interval '1 day'

过去 7 天:

select count(*) from table1
where "Date" > current_timestamp - interval '7 days'

过去 30 天:

select count(*) from table1
where "Date" > current_timestamp - interval '30 days'

过去 3 个月:

select count(*) from table1
where "Date" > current_timestamp - interval '3 months'

确保您在 Date 列上有一个索引。


如果发现索引没有被使用,尝试将条件转换为 between,例如:

where "Date" between current_timestamp - interval '3 months' and current_timestamp

逻辑上相同,但可能有助于优化器选择索引。


注意column1与问题无关;由于是唯一的,因此 row 计数不可能不同于任何给定条件找到的 column1 的不同值的数量。

此外,为列名选择“日期”也很糟糕,因为 a) 它是保留字,b) 实际上不是日期。

【讨论】:

【参考方案2】:

如果要计算两个日期之间的记录数:

select count(*)
from Table1
where "Date" >= '2013-05-12' and "Date" < '2013-05-13'
-- count for one day, upper bound not included

select count(*)
from Table1
where "Date" >= '2013-05-12' and "Date" < '2013-06-13'
-- count for one month, upper bound not included

select count(*)
from Table1
where
    "Date" >= current_date and
    "Date" < current_date + interval '1 day'
-- current date

【讨论】:

谢谢罗马,这真的很有帮助,如果我需要每天计算而不提及日期并让自己使用系统日期,那么我应该使用什么 now() 条件查询?例如,哪个可以获取我的系统日期并相应地查询?只是好奇 如何提高效率,目前处理每个查询需要 175854 毫秒。任何建议都会很棒!【参考方案3】:

我从你的措辞中理解是

select date_trunc('day', "date"), count(*)
from t
where "date" >= '2013-01-01'
group by 1
order by 1

根据需要将'day' 替换为'week''month'、'quarter'。

http://www.postgresql.org/docs/current/static/functions-datetime.html#FUNCTIONS-DATETIME-TRUNC

在“日期”列上创建索引。

【讨论】:

【参考方案4】:
select count(distinct column1) from table1 where date > '2012-05-12 23:03:22';

我假设“column1 的数量”是指“column1 中不同值的数量。

编辑: 关于您的第二个问题(查询速度):我假设日期列上的索引应该加快运行时间。根据数据内容,这甚至可以声明为unique

【讨论】:

谢谢弗兰克,是的,这是不同的价值观。我将如何计算每天。我需要使用 TO_DATE 吗?以获得有效的结果。如果我错了,请纠正我。 “一天内”用今天前一天作为参数,“上周内”用今天前一周作为参数。【参考方案5】:

加入另一个选项...

添加一个类型为“date”的列和索引——在这个例子中命名为“datecol”:

create index on tbl_datecol_idx on tbl (datecol);
analyze tbl;

那么您的查询可以使用相等运算符:

select count(*) from tbl where datecol = current_date - 1; --yesterday

或者,如果您无法添加日期数据类型列,您可以在现有列上创建功能索引:

create index tbl_date_fbi on tbl ( ("date"::DATE) );
analyze tbl;
select count(*) from tbl where "date"::DATE = current_date - 1;

注意1:您不需要直接查询“column1”,因为每一行都由于NOT NULL而填充了该属性。

注意2:创建一个名为“date”的列的形式很糟糕,更糟糕的是它的类型是TIMESTAMP

【讨论】:

以上是关于使用选定时间段从数据库中的一列或两列中计算大量内容的有效方法的主要内容,如果未能解决你的问题,请参考以下文章

EXCEL中如何将两列的内容合并到一列中?

使用pandas创建稀疏矩阵,并使用来自.dat文件的其他两列的索引[x,y]的.dat文件的一列中的值填充它

从不同表的另一列中的一列中查找所有值

将数据从一列插入另一个表的两列的过程

Android:在两列中显示信息,而不是 BaseAdapter 的一列

excel2013使用分列功能拆分数据