PHP 怎么PHP 指标聚合

wen PHP项目 2

本文目录导读:

PHP 怎么PHP 指标聚合

  1. 数组聚合(纯 PHP 处理)
  2. SQL 聚合(推荐方式)
  3. 多维数组聚合
  4. 使用 array_reduce 函数
  5. 使用集合类库(需要 Composer)
  6. 时间序列聚合示例
  7. 性能建议

在 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'];
}

性能建议

  1. 尽可能在数据库层面聚合 - SQL 的 GROUP BY 比 PHP 内存循环快得多
  2. 使用索引 - 确保 GROUP BY 的字段有索引
  3. 分批处理大数据 - 对百万级数据,考虑分块处理
  4. 使用缓存 - 聚合结果如果变化不大,可以缓存
// 数据库聚合与缓存示例
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;
}

选择哪种方式取决于你的具体场景:数据量大小、实时性要求、是否已使用框架等。

抱歉,评论功能暂时关闭!