統計 heart_active 欄位(0/1)在不同日期的筆數,按日期分組排序。初始 SQL 因 input_date 含時分秒(YYYY-MM-DD HH24:MI:SS)導致無法正確按「日」分組。
TRUNC(input_date, 'DD') -- 或 TRUNC(input_date) 預設截至日
將 datetime 統一截斷為當日 00:00:00,實現正確分組。
SELECT TRUNC(a.input_date, 'DD') AS dt,
a.heart_active,
SUM(DECODE(a.heart_active, 1, 1, 0, 1)) AS cnt
FROM rfid_fixed_heart a
GROUP BY TRUNC(a.input_date, 'DD'), a.heart_active
ORDER BY dt DESC;
輸出:每日每狀態一行(0 一行、1 一行)。
SELECT TRUNC(a.input_date, 'DD') AS dt,
SUM(DECODE(a.heart_active, '0', 1)) AS heart_active_0,
SUM(DECODE(a.heart_active, '1', 1)) AS heart_active_1
FROM rfid_fixed_heart a
GROUP BY TRUNC(a.input_date, 'DD')
ORDER BY dt DESC;
輸出:每日一行,兩狀態分列。報表友好,最常用。
SELECT TRUNC(input_date, 'DD') AS dt,
SUM(CASE WHEN heart_active = '0' THEN 1 END) AS heart_active_0,
SUM(CASE WHEN heart_active = '1' THEN 1 END) AS heart_active_1
FROM rfid_fixed_heart
GROUP BY TRUNC(input_date, 'DD')
ORDER BY dt DESC;
SELECT op_date, heart_active,
SUM(heart_active_0) AS heart_active_0,
SUM(heart_active_1) AS heart_active_1
FROM (
SELECT TO_CHAR(input_date, 'YYYY-MM-DD') AS op_date,
heart_active,
CASE WHEN heart_active = '0' THEN COUNT(heart_active) ELSE 0 END AS heart_active_0,
CASE WHEN heart_active = '1' THEN COUNT(heart_active) ELSE 0 END AS heart_active_1
FROM rfid_fixed_heart
GROUP BY input_date, heart_active
) a
GROUP BY op_date, heart_active
ORDER BY op_date DESC;
邏輯較繞,不推薦生產使用,僅供理解轉換思路。
| 技術點 | 說明 |
|---|---|
| TRUNC(date) | 截取日期部分,預設 'DD',支援 'MM'、'YYYY'、'HH24'、'MI' 等 |
| DECODE | Oracle 專用,簡潔但非標準;DECODE(col, val1, ret1, val2, ret2, default) |
| CASE WHEN | ANSI 標準,支援複雜條件(範圍、多欄位)、可讀性強 |
| GROUP BY 截取後欄位 | 必須與 SELECT 列表一致,否則 ORA-00979 |
| 資料型別一致 | heart_active 為 VARCHAR2,比較值需加單引號 '0'/'1' |
input_date 有索引,或建立 函數索引 CREATE INDEX idx_trunc_date ON rfid_fixed_heart(TRUNC(input_date))。WHERE TRUNC(dt) = ...),改用範圍查詢 dt >= TRUNC(SYSDATE) AND dt < TRUNC(SYSDATE)+1 走索引。