原始表記錄每日各事件(下載點擊、成功點擊、安裝成功)的 UV 值,需轉為「一行一日期,多列事件指標」的寬表,供報表直連查詢。
biz_date event uv 2023-01-01 downClick 100 2023-01-01 successClick 80 2023-01-01 installSuccess 60 2023-01-02 downClick 120 ...

biz_date downClick successClick installSuccess 2023-01-01 100 80 60 2023-01-02 120 90 70 ...

SELECT
a.biz_date,
SUM(CASE WHEN a.`event` = 'downClick' THEN a.uv END) AS downClick,
SUM(CASE WHEN a.`event` = 'successClick' THEN a.uv END) AS successClick,
SUM(CASE WHEN a.`event` = 'installSuccess' THEN a.uv END) AS installSuccess
FROM a
GROUP BY a.biz_date
ORDER BY a.biz_date;
CASE WHEN ... THEN ... END:非匹配行返回 NULL,SUM() 自動忽略 NULL,等同於條件求和。ELSE 0,SUM(NULL) 為 NULL,外層可用 COALESCE(...,0) 顯示 0。GROUP BY biz_date 將多行壓縮為單行,實現行→列轉換。MySQL 不支持動態列輸出,需兩步:
-- 步驟 1:獲取所有事件類型
SELECT GROUP_CONCAT(DISTINCT CONCAT('SUM(CASE WHEN `event`=', QUOTE(`event`), ' THEN uv END) AS ', `event`))
FROM a INTO @sql;
-- 步驟 2:構建並執行動態 SQL
SET @sql = CONCAT('SELECT biz_date, ', @sql, ' FROM a GROUP BY biz_date ORDER BY biz_date');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SELECT
biz_date,
SUM(CASE WHEN `event`='downClick' THEN uv END) AS downClick_uv,
SUM(CASE WHEN `event`='downClick' THEN pv END) AS downClick_pv,
SUM(CASE WHEN `event`='downClick' THEN duration END) AS downClick_dur,
...
FROM a
GROUP BY biz_date;
WITH daily AS (
SELECT
biz_date,
SUM(CASE WHEN `event`='downClick' THEN uv END) AS downClick
FROM a GROUP BY biz_date
)
SELECT
biz_date,
downClick,
LAG(downClick) OVER (ORDER BY biz_date) AS prev_day,
ROUND(100.0 * (downClick - LAG(downClick) OVER (ORDER BY biz_date)) / NULLIF(LAG(downClick) OVER (ORDER BY biz_date),0), 2) AS mom_pct
FROM daily;
(biz_date, `event`),加速分組掃描。SELECT *,只讀取所需列(覆蓋索引)。MySQL 無原生 PIVOT(SQL Server)或 CROSSTAB(PostgreSQL/Oracle),條件聚合是標準、可移植、高性能的通用方案。
掌握此模式,靈活應對各類報表透視需求,無需依賴應用層二次處理。