gpt4 book ai didi

php - 按固定日期间隔选择并分组

转载 作者:行者123 更新时间:2023-11-29 07:26:35 25 4
gpt4 key购买 nike

我正在研究一个基于 MySQL 时间的大型统计表。

我有一个固定的时间范围(开始和结束日期时间对象)并在 ISO-8601 中获取间隔字符串像 P1DT6H 一样的间隔字符串作为 PHP 对象,其中范围中的开始日期也是间隔的起点,并且还定义了间隔使用的时区。

现在我想选择给定时间范围内按此间隔分组的所有数据,但即使经过很多小时也无法使其工作:(

例如,我得到的时间范围为 2015-09-01/2015-09-06 ,间隔为 P1DT6H 以及以下示例表:

TIMESTAMP           | count
2015-09-01 00:00:00 | 1
2015-09-01 02:00:00 | 1
2015-09-01 04:00:00 | 1
2015-09-01 06:00:00 | 1
2015-09-01 08:00:00 | 1
2015-09-01 10:00:00 | 1
2015-09-01 12:00:00 | 1
2015-09-01 14:00:00 | 1
2015-09-01 16:00:00 | 1
2015-09-01 18:00:00 | 1
2015-09-01 20:00:00 | 1
2015-09-01 22:00:00 | 1
2015-09-03 00:00:00 | 1
2015-09-03 02:00:00 | 1
2015-09-03 04:00:00 | 1
2015-09-03 06:00:00 | 1
2015-09-03 08:00:00 | 1
2015-09-03 10:00:00 | 1
2015-09-03 12:00:00 | 1
2015-09-03 14:00:00 | 1
2015-09-03 16:00:00 | 1
2015-09-03 18:00:00 | 1
2015-09-03 20:00:00 | 1
2015-09-03 22:00:00 | 1
2015-09-05 00:00:00 | 1
2015-09-05 02:00:00 | 1
2015-09-05 04:00:00 | 1
2015-09-05 06:00:00 | 1
2015-09-05 08:00:00 | 1
2015-09-05 10:00:00 | 1
2015-09-05 12:00:00 | 1
2015-09-05 14:00:00 | 1
2015-09-05 16:00:00 | 1
2015-09-05 18:00:00 | 1
2015-09-05 20:00:00 | 1
2015-09-05 22:00:00 | 1

我希望得到以下结果:

TIMESTAMP           | count
2015-09-01 00:00:00 | 12
2015-09-02 06:00:00 | 6
2015-09-03 12:00:00 | 6
2015-09-04 18:00:00 | 12

当然间隔可以更复杂,时间范围可以很大,数据表也很大。

这需要处理几乎每个月都有不同天数的月份,包括。闰年和夏令时也会发生变化,一天可以有 23、24 或 25 小时。 (意味着一天间隔不同于 24 小时间隔)

如果有人有解决方案或者我能为此类问题指出正确的方向,那将非常有帮助。

谢谢!

PS:我有一个脚本,可以在给定数据库列、开始、结束和间隔对象的基础上创建 SQL 表达式,但它仅适用于非常简单的间隔,例如 P1D。我不会在这里跳过它,因为我不想让所有伟大的大脑进入我已经拥有的非工作方向;)

我现在拥有的,但它不适用于混合间隔。示例:

时区处理:

if ($db->getTimezone()->getName() !== $start->getTimezone()->getName()) {
$col = 'CONVERT_TZ(' . $col
. ', ' . $this->quote($this->getTimezone()->getName())
. ', ' . $this->quote($start->getTimezone()->getName())
. ')';
}

P1M:

$m = ($interval->y * 12) + $interval->m;
if ($m) {
if ($m > 1) {
$mod = $start->format('Ym') % $m;
$mod = $mod ? ' + ' . $mod : '';
$expr = 'EXTRACT(YEAR_MONTH FROM ' . $col . ')';
$expr = $mod ? '(' . $expr . $mod . ')' : $expr;
$expr = ' - INTERVAL ' . $expr . ' % ' . $m . ' MONTH';
$sqlIntervalMonth = $expr;
}
$sqlIntervalDay = ' - INTERVAL DAY(' . $col . ') - 1 DAY';
if ($start->format('d') > 1) {
$sqlIntervalDay .= ' + INTERVAL ' . ($start->format('d') - 1) . ' DAY';
}
}

P1D:

$d = $interval->d;
if ($d) {
$days = $start->diff(new DateTime('0000-00-00'))->days;
$mod = $days % $d;
$mod = $mod ? ' + ' . $mod : '';
$expr = 'TO_DAYS(' . $col . ')';
$expr = $mod ? '(' . $expr . $mod . ')' : $expr;
$expr = ' - INTERVAL ' . $expr . ' % ' . $d . ' DAY';
$sqlIntervalDay = $expr;
}

编辑1:指出时区、夏令时和闰年要求。编辑2:添加了PHP片段

最佳答案

一个想法是将时间戳的值转换为秒,然后将该值舍入到适当的间隔(在您的情况下为 36 小时)。像这样的事情:

select min(timestamp) as timestamp, sum(count)
from t
group by floor(to_seconds(timestamp) / 60 * 60 * 36) -- * 60 * 60 * 36
order by timestamp;

这使用了日期时间值的min(),因为表中似乎有该值。或者,您可以将四舍五入的秒数转换回日期时间值。

关于php - 按固定日期间隔选择并分组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34333558/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com