數據分析場景中,頁面訪問統計(PV/UV、分辨率分布、趨勢圖)是高頻需求。本文提供開箱即用的 MySQL 查詢語句,覆蓋分辨率排名、最近 7/30 天趨勢、昨日 24 時分時、今日小時級統計等核心指標。
SELECT
CONCAT(`height`, '*', `width`) AS `resolution`,
COUNT(*) AS `total`
FROM `wifi_status_page`
GROUP BY `resolution`
ORDER BY `total` DESC
LIMIT 0, 30;
優化點:CONCAT 直接在 GROUP BY 中復用別名(MySQL 8.0+ 支持),避免重複計算。
SELECT
a.td AS showdate,
COALESCE(b.totalcount, 0) AS totalcount
FROM (
SELECT CURDATE() AS td UNION ALL
SELECT DATE_ADD(CURDATE(), INTERVAL -1 DAY) UNION ALL
SELECT DATE_ADD(CURDATE(), INTERVAL -2 DAY) UNION ALL
SELECT DATE_ADD(CURDATE(), INTERVAL -3 DAY) UNION ALL
SELECT DATE_ADD(CURDATE(), INTERVAL -4 DAY) UNION ALL
SELECT DATE_ADD(CURDATE(), INTERVAL -5 DAY) UNION ALL
SELECT DATE_ADD(CURDATE(), INTERVAL -6 DAY)
ORDER BY td
) a
LEFT JOIN (
SELECT
FROM_UNIXTIME(add_time, '%Y-%m-%d') AS add_data,
COUNT(id) AS totalcount
FROM wifi_status_page
WHERE FROM_UNIXTIME(add_time, '%Y-%m-%d') BETWEEN DATE_ADD(CURDATE(), INTERVAL -6 DAY) AND CURDATE()
GROUP BY add_data
) b ON a.td = b.add_data;
核心技巧:
a 生成連續 7 天日期序列(日曆表模式)LEFT JOIN 確保無數據日期顯示 0(COALESCE)FROM_UNIXTIME 統一時間戳轉日期,利用索引範圍查詢SELECT
a.td AS showdate,
COALESCE(b.totalcount, 0) AS totalcount
FROM (
SELECT CURDATE() AS td UNION ALL
SELECT DATE_ADD(CURDATE(), INTERVAL -1 DAY) UNION ALL
-- ... 重複至 INTERVAL -29 DAY
SELECT DATE_ADD(CURDATE(), INTERVAL -29 DAY)
ORDER BY td
) a
LEFT JOIN (
SELECT
FROM_UNIXTIME(add_time, '%Y-%m-%d') AS add_data,
COUNT(id) AS totalcount
FROM wifi_status_page
WHERE FROM_UNIXTIME(add_time, '%Y-%m-%d') BETWEEN DATE_ADD(CURDATE(), INTERVAL -29 DAY) AND CURDATE()
GROUP BY add_data
) b ON a.td = b.add_data;
💡 生產建議:創建永久日曆表 dim_date,替代 UNION ALL 生成序列,提升可讀性與性能。
SELECT
DATE_ADD(CURDATE(), INTERVAL -1 HOUR) AS td UNION ALL
SELECT DATE_ADD(CURDATE(), INTERVAL -2 HOUR) UNION ALL
-- ... 重複至 INTERVAL -24 HOUR
SELECT DATE_ADD(CURDATE(), INTERVAL -24 HOUR)
ORDER BY td;
此查詢僅生成時間序列,需 LEFT JOIN 實際訪問表獲取計數,邏輯同每日趨勢。
SELECT NOW() AS td UNION ALL
SELECT DATE_ADD(NOW(), INTERVAL -1 HOUR) UNION ALL
-- ... 重複至 INTERVAL -11 HOUR
SELECT DATE_ADD(NOW(), INTERVAL -11 HOUR)
ORDER BY td;
使用 NOW() 而非 CURDATE(),精確到小時級時間窗口。
add_time 建立單列索引;高頻查詢可建立聯合索引 (add_time, height, width) 覆蓋分辨率統計。WHERE FROM_UNIXTIME(add_time, ...) = '2024-01-15' 會導致全表掃描。WHERE add_time BETWEEN UNIX_TIMESTAMP('2024-01-15') AND UNIX_TIMESTAMP('2024-01-16')wifi_status_page_daily,定時任務刷新,查詢毫秒級返回。time_zone、應用層、數據寫入層時區統一(建議均用 UTC)。將上述邏輯封裝為存儲過程或應用層工具類:
-- 存儲過程示例:獲取任意天數趨勢
CREATE PROCEDURE `sp_page_trend`(IN days INT)
BEGIN
SET @sql = CONCAT('
SELECT a.td AS showdate, COALESCE(b.totalcount, 0) AS totalcount
FROM (
SELECT CURDATE() AS td ',
REPEAT('UNION ALL SELECT DATE_ADD(CURDATE(), INTERVAL -', days, ' DAY) '),
'ORDER BY td
) a
LEFT JOIN (
SELECT FROM_UNIXTIME(add_time, ''%Y-%m-%d'') add_data, COUNT(id) totalcount
FROM wifi_status_page
WHERE add_time BETWEEN UNIX_TIMESTAMP(DATE_ADD(CURDATE(), INTERVAL -', days, ' DAY))
AND UNIX_TIMESTAMP(DATE_ADD(CURDATE(), INTERVAL 1 DAY))
GROUP BY add_data
) b ON a.td = b.add_data
');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END;
「日曆表 LEFT JOIN 業務表」是時序統計的標準范式,解決「無數據日期/小時顯示 0」的核心痛點。結合範圍查詢利用索引、預聚合表應對大數據量,可構建高性能、易維護的訪問統計體系。