部落格、CMS 系統常需「文章歸檔」功能:依發布時間分組統計文章數,生成側邊欄歸檔清單。本文提供針對 Unix 時間戳 與 DATETIME/TIMESTAMP 兩種儲存格式的完整 SQL 查詢範例,並示範格式化輸出與分頁限制。
SELECT
FROM_UNIXTIME(pubtime, '%Y-%m') AS pubtime,
COUNT(*) AS cnt
FROM articles
GROUP BY FROM_UNIXTIME(pubtime, '%Y-%m')
ORDER BY pubtime DESC;
輸出範例:
| pubtime | cnt |
|---|---|
| 2024-01 | 15 |
| 2023-12 | 22 |
SELECT
FROM_UNIXTIME(pubtime, '%Y-%m-%d') AS pubtime,
COUNT(*) AS cnt
FROM articles
GROUP BY FROM_UNIXTIME(pubtime, '%Y-%m-%d')
ORDER BY pubtime DESC;
使用 DATE_FORMAT() 直接格式化欄位,無需轉換。
SELECT
DATE_FORMAT(`post_date`, '%Y%m%d') AS pubtime,
COUNT(*) AS cnt
FROM wp_posts
WHERE `post_status` = 'publish'
GROUP BY DATE_FORMAT(`post_date`, '%Y%m%d')
ORDER BY `ID` DESC;
SELECT
DATE_FORMAT(`post_date`, '%Y%m%d') AS pubtime,
DATE_FORMAT(`post_date`, '%m 月 %d 日') AS shijian, -- 顯示用「01 月 15 日」
COUNT(*) AS cnt
FROM wp_posts
WHERE `post_status` = 'publish'
GROUP BY DATE_FORMAT(`post_date`, '%Y%m%d')
ORDER BY `ID` DESC
LIMIT 0, 7; -- 只取近 7 筆
輸出範例:
| pubtime | shijian | cnt |
|---|---|---|
| 20240115 | 01 月 15 日 | 3 |
| 20240110 | 01 月 10 日 | 1 |
<?php
function getArchiveList(PDO $pdo, int $limit = 12): array
{
$sql = "
SELECT
DATE_FORMAT(`post_date`, '%Y-%m') AS ym,
COUNT(*) AS cnt
FROM wp_posts
WHERE `post_status` = 'publish'
GROUP BY DATE_FORMAT(`post_date`, '%Y-%m')
ORDER BY ym DESC
LIMIT :limit
";
$stmt = $pdo->prepare($sql);
$stmt->bindValue(':limit', $limit, PDO::PARAM_INT);
$stmt->execute();
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
// 使用
$archives = getArchiveList($pdo, 12);
?>
<aside class="widget-archive">
<h3>文章歸檔</h3>
<ul>
<?php foreach ($archives as $row): ?>
<li>
<a href="/archive/<?= $row['ym'] ?>">
<?= date('Y 年 m 月', strtotime($row['ym'] . '-01')) ?> (<?= $row['cnt'] ?>)
</a>
</li>
<?php endforeach; ?>
</ul>
</aside>
pub_year_month CHAR(7)(如 '2024-01'),寫入時同步填入,查詢直接 GROUP BY pub_year_month 即可用上索引。INDEX idx_status_ym (post_status, pub_year_month) 覆蓋 WHERE 與 GROUP BY。RANGE (YEAR(post_date)) 分區。| 代碼 | 含義 | 範例 |
|---|---|---|
| %Y | 四位數年份 | 2024 |
| %m | 兩位數月份 | 01 |
| %d | 兩位數日期 | 15 |
| %c | 月份數值 | 1 |
| %e | 日期數值 | 15 |
| %M | 英文月份全名 | January |
| %b | 英文月份縮寫 | Jan |
歸檔查詢核心在於 FROM_UNIXTIME()(時間戳)或 DATE_FORMAT()(日期時間型別)搭配 GROUP BY。實務上強烈建議新增冗餘格式化欄位並建立索引,避免函數導致全表掃描,確保歸檔側邊欄毫秒級回應。