表及时分配

我有一个每个用户大约有3000行的MySQL表。其中一列是日期时间字段,它是可变的,所以行不按时间顺序排列。

我想在图表中将时间分布可视化,所以我需要一些单独的数据点。 20个数据点就足够了。

我可以这样做:

select timefield from entries where uid = ? order by timefield;

并看看每150行。

或者我可以做20个单独的查询并使用 limit 1offset

但是必须有更高效的解决方案......

0
额外 编辑
意见: 1
你能更详细地描述这个问题吗?你在找什么输出?你是否想要查看频率图(例如:Jan = 132,Feb = 112,Mar = 173等)中的条目数量,还是希望最早的条目,第150条最早的条目,第300条条目的个别值,等等?
额外 作者 nickf,

7 答案

对于我的参考 - 对于那些使用postgres的人来说 - Postgres 9.4将会有有序的集合来解决这个问题:

SELECT percentile_disc(0.95) 
WITHIN GROUP (ORDER BY response_time) 
FROM pageviews;

Source: http://www.craigkerstiens.com/2014/02/02/Examining-PostgreSQL-9.4/

0
额外

@Michal

无论出于何种原因,您的示例仅适用于where @recnum使用少于运算符的情况。我认为,当过滤掉某一行时,rownum不会增加,并且不能与其他任何内容匹配。

如果原始表格有一个自动递增的id列,并且行按时间顺序插入,那么这应该工作:

select timefield from entries
where uid = ? and id % 150 = 0 order by timefield;

当然,如果id和时间域之间没有关联,那么这种方法就行不通,除非你实际上并不关心获得均匀间隔的时间域,只有20个随机域。

0
额外

我想起了这样的事情

select @rownum:[email protected]+1 rownum, entries.* 
from (select @rownum:=0) r, entries 
where uid = ? and rownum % 150 = 0

我手边没有MySQL,但也许这会帮助...

0
额外

就可视化而言,我知道这不是您正在讨论的定期采样,但是我会查看用户的所有行并选择一个间隔存储桶,SUM存储在存储桶中并显示在条形图或类似图表上。这将显示一个真正的“分布”,因为在一个时间范围内的多次事件可能是重要的。

SELECT DATEADD(day, DATEDIFF(day, 0, timefield), 0) AS bucket -- choose an appropriate granularity (days used here)
     ,COUNT(*)
FROM entries
WHERE uid = ?
GROUP BY DATEADD(day, DATEDIFF(day, 0, timefield), 0)
ORDER BY DATEADD(day, DATEDIFF(day, 0, timefield), 0)

或者,如果您不喜欢重复自己的方式 - 或者如果您在使用不同的存储桶,并且想要以三维方式在许多用户中进行分析(以Z,x,y,uid,桶形式衡量):

SELECT uid
    ,bucket
    ,COUNT(*) AS measure
FROM (
    SELECT uid
        ,DATEADD(day, DATEDIFF(day, 0, timefield), 0) AS bucket
    FROM entries
) AS buckets
GROUP BY uid
    ,bucket
ORDER BY uid
    ,bucket

如果我想以三维方式进行绘图,那么我可能会根据用户的一些有意义的总体指标确定一种方式来订购用户。

0
额外
不,你不能,但是,优化器不会重新计算这些表达式,因为它知道这些函数是确定性的。
额外 作者 Cade Roux,
你可以做“GR​​OUP BY桶ORDER BY桶”吗?看起来好像效率更高(不必每次重新计算该列)
额外 作者 nickf,

Michal Sznajder几乎拥有它,但不能在SQL中的WHERE子句中使用列别名。所以你必须把它作为派生表来包装。我试过了,它返回20行:

SELECT * FROM (
    SELECT @rownum:[email protected]+1 AS rownum, e.*
    FROM (SELECT @rownum := 0) r, entries e) AS e2
WHERE uid = ? AND rownum % 150 = 0;
0
额外
select timefield
from entries
where rand() = .01 --will return 1% of rows adjust as needed.

不是MySQL专家,所以我不确定rand()在这个环境中如何运行。

0
额外
应该是“rand()<.01”
额外 作者 nickf,

你真的关心个人数据点吗?或者将使用日数字上的统计聚合函数来代替告诉你你想知道什么?

0
额外