在專案開發過程中,我們常會重複使用成熟的代碼片段。適時總結、優化這些代碼,不僅能提升開發效率,還能發現更優雅、高效的實現方式。優秀的開發者不僅關注代碼量,更追求代碼的簡潔性、邏輯清晰度與實現的便捷性。本文分享一個實用的 PHP 技巧:以特定字段為索引返回數據庫查詢的二維數組,能大幅簡化後續數據處理邏輯。
假設需要建立一個後台報表,統計各合作站點每日帶來的流量。需求:列出所有配置站點,即使某站點當天無流量也要顯示(流量顯示為 0)。
為了性能考量,根據讀寫特性選擇不同存儲引擎:
-- 站點配置表
CREATE TABLE `site_config` (
`id` smallint(5) unsigned NOT NULL AUTO_INCREMENT COMMENT '主鍵,自增',
`sid` smallint(5) unsigned NOT NULL COMMENT '網站ID',
`site_url` varchar(128) NOT NULL COMMENT '網站URL地址',
`site_name` varchar(80) NOT NULL COMMENT '網站名稱',
`add_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '添加時間',
PRIMARY KEY (`id`),
UNIQUE KEY `adid` (`sid`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='站點配置表';
-- 站點流量統計表
CREATE TABLE `site_stat` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主鍵,自增',
`sid` smallint(5) unsigned NOT NULL COMMENT '網站ID',
`ip_address` varchar(32) NOT NULL COMMENT '用戶IP',
`add_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '添加時間',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='站點流量統計表';
site_config
| id | sid | site_url | add_time |
|---|---|---|---|
| 1 | 200 | baidu.com | 2013-06-30 14:20:00 |
| 2 | 201 | google.com | 2013-06-30 14:20:00 |
| 3 | 202 | cnblogs.com | 2013-06-30 14:20:00 |
| 4 | 203 | codejia.net | 2013-06-30 14:20:00 |
site_stat
| id | sid | ip_address | add_time |
|---|---|---|---|
| 1 | 200 | 167.87.32.4 | 2013-06-30 14:40:00 |
| 2 | 200 | 192.168.11.56 | 2013-06-30 14:40:10 |
| 3 | 202 | 167.87.32.4 | 2013-06-30 14:40:10 |
| 4 | 202 | 192.168.11.56 | 2013-06-30 14:40:20 |
| 5 | 203 | 167.87.32.4 | 2013-06-30 14:40:20 |
| 6 | 202 | 10.10.10.10 | 2013-06-30 14:40:30 |
| 7 | 200 | 167.87.32.4 | 2013-06-30 14:40:31 |
避免複雜的 LEFT JOIN 與 GROUP BY,改用兩條簡單 SQL 分別查詢,再在 PHP 層合併:
SELECT sid, site_url, site_name FROM site_config
SELECT sid, COUNT(1) AS come_total FROM site_stat
WHERE add_time >= '2013-06-30 00:00:00'
AND add_time <= '2013-06-30 23:59:59'
GROUP BY sid
此函數可選擇性地以指定字段為鍵名返回二維數組:
protected function getList($sql, $field = null) {
$res = mysql_query($sql, $this->link_sc);
$data = array();
if ($field === null) {
while ($row = mysql_fetch_assoc($res)) {
$data[] = $row;
}
} else {
while ($row = mysql_fetch_assoc($res)) {
$data[$row[$field]] = $row;
}
}
return $data;
}
$sites = getList($sql1); // 所有站點,數字索引
$data = getList($sql2, 'sid'); // 流量數據,以 sid 為索引
// 輸出報表
foreach ($sites as $site) {
$sid = $site['sid'];
$come_total = isset($data[$sid]) ? $data[$sid]['come_total'] : 0;
echo "{$date},{$sid},{$site['site_url']},{$come_total}\n";
}
2013-06-30,200,baidu.com,3
2013-06-30,201,google.com,0
2013-06-30,202,cnblogs.com,3
2013-06-30,203,codejia.net,1
這個小技巧通過「以業務鍵為索引」的方式,將數據庫層面的連接操作轉移到應用層的數組查找,代碼更清晰、維護更容易,且避免了複雜 SQL 帶來的性能隱患。建議在類似「主表全量 + 子表聚合」的場景中常態化使用,並持續總結沉澱自己的代碼庫。