首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP 專案實戰:快速排序演算法於促銷價排序的應用

     編輯:PHP 綜合知識

業務痛點

商品列表需支援「價格高→低」排序。但部分商品處於促銷期,應以 `promote_price` 參與排序,而資料庫 `ORDER BY` 無法直接處理「動態價格」邏輯。

解決策略:兩階段排序

  1. 資料庫先按原價 `goods_price` 排序取出當頁資料 (分頁)。
  2. PHP 端遍歷判斷促銷有效性,將有效促銷價覆蓋至 `price` 欄位。
  3. 對結果集執行**快速排序**,以最終 `price` 為基準重新排序。

通用二維陣列快速排序函式

/**
 * 二維陣列快速排序
 * @param array $rows  資料集 [ ['id'=>1, 'price'=>100], ... ]
 * @param string $key  排序欄位名
 * @param string $order 'asc' 或 'desc'
 * @return array 排序後新陣列,保留原鍵名
 */
function quickSort2D(array $rows, string $key, string $order = 'asc'): array {
    if (count($rows) <= 1) return $rows;

    // 提取排序鍵值對應表 [原鍵 => 排序值]
    $kv = [];
    foreach ($rows as $k => $v) {
        if (!isset($v[$key])) continue; // 忽略缺失欄位
        $kv[$k] = $v[$key];
    }

    // 使用 PHP 內建排序 (C 實現,效能遠超純 PHP 遞迴)
    if ($order === 'desc') {
        arsort($kv);
    } else {
        asort($kv);
    }

    // 按排序後的鍵名重組
    $sorted = [];
    foreach ($kv as $k => $v) {
        $sorted[$k] = $rows[$k];
    }
    return $sorted;
}

為什麼不手寫遞迴 QuickSort?

  • PHP 內建 `asort`/`arsort` 由 C 實現,速度比純 PHP 遞迴快 **10~100 倍**。
  • 手寫遞迴在 PHP 中極易觸發「最大執行時間」或「記憶體耗盡」。
  • 鍵名保留特性完美符合「不丟失原索引」需求。

完整業務流程範例

// 1. 取得資料 (已按原價排序)
$goods = $db->query("SELECT id, goods_price, promote_price, promote_start, promote_end FROM goods WHERE cat_id=5 ORDER BY goods_price ASC LIMIT 20");

// 2. 判斷促銷有效性,計算顯示價
$now = time();
foreach ($goods as &$g) {
    if ($g['promote_price'] > 0 && $now >= $g['promote_start'] && $now <= $g['promote_end']) {
        $g['display_price'] = $g['promote_price'];
        $g['is_promote'] = true;
    } else {
        $g['display_price'] = $g['goods_price'];
        $g['is_promote'] = false;
    }
}
unset($g); // 解除引用

// 3. 以 display_price 重新排序
$sorted = quickSort2D($goods, 'display_price', 'asc');

// 4. 輸出模板
foreach ($sorted as $g) {
    echo $g['is_promote'] ? "🔥 {$g['display_price']}" : $g['display_price'];
}

效能補充:大資料量怎麼辦?

若單頁超過 1000 筆,建議:

  1. 將促銷邏輯下推到 SQL:`SELECT ..., IF(promote_valid, promote_price, goods_price) AS display_price ... ORDER BY display_price` (需將促銷有效性預先計算存欄位或用視圖)。
  2. 或使用 Redis 緩存已排序的商品 ID 列表,定期重建。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved