本文目录导读:

在 PHP 中实现指标聚合(类似数据库的 GROUP BY + SUM/COUNT/AVG),通常有以下几种常见场景和对应的实现方式:
数组聚合(纯 PHP 处理)
适用于从数据库取回数据后,需要在 PHP 内存中进一步聚合。
<?php
$data = [
['category' => 'A', 'amount' => 100],
['category' => 'A', 'amount' => 200],
['category' => 'B', 'amount' => 150],
['category' => 'B', 'amount' => 250],
['category' => 'C', 'amount' => 300],
];
// 按 category 聚合求和
$aggregated = [];
foreach ($data as $item) {
$cat = $item['category'];
if (!isset($aggregated[$cat])) {
$aggregated[$cat] = [
'category' => $cat,
'total' => 0,
'count' => 0,
];
}
$aggregated[$cat]['total'] += $item['amount'];
$aggregated[$cat]['count']++;
}
// 输出结果
print_r(array_values($aggregated));
SQL 聚合(推荐方式)
直接在数据库层面聚合,性能更好:
<?php
$pdo = new PDO('mysql:host=localhost;dbname=test', 'root', '');
// 原始 SQL 聚合
$stmt = $pdo->query("
SELECT
category,
SUM(amount) as total,
COUNT(*) as count,
AVG(amount) as avg_amount
FROM orders
GROUP BY category
");
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
多维数组聚合
当需要按多个字段分组时:
<?php
$data = [
['year' => 2023, 'month' => 1, 'sales' => 100],
['year' => 2023, 'month' => 1, 'sales' => 200],
['year' => 2023, 'month' => 2, 'sales' => 150],
['year' => 2024, 'month' => 1, 'sales' => 300],
];
// 多维聚合键
$aggregated = [];
foreach ($data as $item) {
$key = $item['year'] . '-' . $item['month'];
if (!isset($aggregated[$key])) {
$aggregated[$key] = [
'year' => $item['year'],
'month' => $item['month'],
'total_sales' => 0,
];
}
$aggregated[$key]['total_sales'] += $item['sales'];
}
使用 array_reduce 函数
函数式编程风格的聚合:
<?php
$data = [
['category' => 'A', 'amount' => 100],
['category' => 'A', 'amount' => 200],
['category' => 'B', 'amount' => 150],
];
$aggregated = array_reduce($data, function($carry, $item) {
$cat = $item['category'];
if (!isset($carry[$cat])) {
$carry[$cat] = ['category' => $cat, 'total' => 0, 'count' => 0];
}
$carry[$cat]['total'] += $item['amount'];
$carry[$cat]['count']++;
return $carry;
}, []);
print_r(array_values($aggregated));
使用集合类库(需要 Composer)
安装 illuminate/collections(Laravel 的集合类):
composer require illuminate/collections
<?php
require 'vendor/autoload.php';
use Illuminate\Support\Collection;
$data = new Collection([
['category' => 'A', 'amount' => 100],
['category' => 'A', 'amount' => 200],
['category' => 'B', 'amount' => 150],
]);
$aggregated = $data->groupBy('category')->map(function($items) {
return [
'category' => $items->first()['category'],
'total' => $items->sum('amount'),
'count' => $items->count(),
];
});
print_r($aggregated->values()->all());
时间序列聚合示例
对时间数据进行按小时、天、月聚合:
<?php
// 按天聚合
$aggregated_by_day = [];
foreach ($time_series_data as $item) {
$day = date('Y-m-d', strtotime($item['timestamp']));
if (!isset($aggregated_by_day[$day])) {
$aggregated_by_day[$day] = 0;
}
$aggregated_by_day[$day] += $item['value'];
}
性能建议
- 尽可能在数据库层面聚合 - SQL 的
GROUP BY比 PHP 内存循环快得多 - 使用索引 - 确保 GROUP BY 的字段有索引
- 分批处理大数据 - 对百万级数据,考虑分块处理
- 使用缓存 - 聚合结果如果变化不大,可以缓存
// 数据库聚合与缓存示例
function getSalesByCategory() {
$cacheKey = 'sales_by_category';
// 尝试从缓存获取
$cached = apcu_fetch($cacheKey);
if ($cached !== false) {
return $cached;
}
// 数据库聚合
$results = $db->query("SELECT category, SUM(amount) as total FROM orders GROUP BY category")->fetchAll();
// 缓存1小时
apcu_store($cacheKey, $results, 3600);
return $results;
}
选择哪种方式取决于你的具体场景:数据量大小、实时性要求、是否已使用框架等。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播