記錄一下今天組了半天的SQL,太久沒用都快忘光了。
原始需求為使用者可在頁面點選[瀏覽器交易錯誤記錄查詢]功能依照日期或月份查詢交易錯誤發生時的瀏覽器資訊及錯誤代碼,畫面類似下面。
瀏覽器交易錯誤記錄查詢
瀏覽器 | 版本 | 錯誤代碼(E001) | 錯誤代碼(E002) |
---|---|---|---|
Chrome | 78 | 3 | 5 |
Chrome | 78 | 9 | 5 |
Firefox | 70 | 3 | 8 |
Firefox | 69 | 5 | 7 |
IE | 11 | 4 | 9 | Safari | 13 | 2 | 1 |
資料來源為交易記錄資料表TX_LOG
,存放每筆交易時的各種資訊,包括瀏覽器資訊及錯誤代碼。
每一次交易發生時就會在TX_LOG
記錄一筆資料,一天交易次數假設有100萬次,那麼就不能等到使用者查詢時才去資料庫查,因為資料量多查詢及計算的時間會太長,所以就利用離峰的時間例如臨晨跑排程(cron job schedule)執行查詢的SQL並把統計結果放到另一個資料表BROWSER_TX_ERROR_DAY_LOG
,這樣使用者在查詢時只要來這份統計後的資料表查詢,速度會比較快。
麻煩的是必須要依瀏覽器類型BROWSER_TYPE
及版本BROWSER_VERSION
來統計不同錯誤代碼ERROR_CODE
的每日總計次數,且各瀏覽器要被統計的版本也不太相同,例如IE 11以下,Chrome 60以下的版本就不統計。
下面是TX_LOG
資料表及其中幾個要被查詢的欄位。
TX_LOG
CREATE TABLE TX_LOG(
...
BROWSER_TYPE VARCHAR2(50), -- 瀏覽器類型 eg.Chrome, Firefox, IE, Safari, Edge, Opera...
BROWSER_VERSION NUMBER(4), -- 瀏覽器主版本
ERROR_CODE VARCHAR(4), -- 錯誤代碼 eg. E001, E002...
CREATE_TIME NUMBER(18)
...
);
下面是查詢TX_LOG
並統計後存放的BROWSER_TX_ERROR_DAY_LOG
資料表
BROWSER_TX_ERROR_DAY_LOG
CREATE BROWSER_TX_ERROR_DAY_LOG(
...
BROWSER_TYPE VARCHAR2(50), -- 瀏覽器類型 eg.Chrome, Firefox, IE, Safari, Edge, Opera...
BROWSER_VERSION NUMBER(4), -- 瀏覽器主版本
ERROR_CODE VARCHAR(4) NOT NULL, -- 錯誤代碼 eg. E001, E002...
ERROR_CODE_DAILY_COUNT NUMBER(4) NOT NULL, -- 錯誤代碼每日總計
CREATE_DATE DATE,
...
);
下面是跑排程統計的查詢SQL,查詢的結果就存入BROWSER_TX_ERROR_DAY_LOG
。
SELECT
BROWSER_TYPE,
BROWSER_VERSION,
ERROR_CODE,
COUNT(ERROR_CODE) AS ERROR_COUNT
FROM (
SELECT
CASE
WHEN BROWSER_TYPE NOT IN ('IE','CHROME', 'FIREFOX','SAFARI','EDGE') THEN 'OTHERS'
WHEN BROWSER_TYPE IS NULL THEN 'OTHERS'
ELSE BROWSER_TYPE
END
AS BROWSER_TYPE,
BROWSER_VERSION,
ERROR_CODE,
CREATE_TIME
FROM TX_LOG
WHERE ERROR_CODE IN ('E001','E002')
AND TO_DATE('1970/01/01', 'YYYY/MM/DD') + (CREATE_TIME/1000/60/60/24) BETWEEN TRUNC(SYSDATE - 1) AND TRUNC(SYSDATE)
)
WHERE 1 = 1
AND (
CASE
WHEN BROWSER_TYPE = 'IE' AND BROWSER_VERSION >= 11 THEN 1
WHEN BROWSER_TYPE IN ('CHROME', 'FIREFOX') AND BROWSER_VERSION >= 60 THEN 1
WHEN BROWSER_TYPE = 'SAFARI' AND BROWSER_VERSION >= 10 THEN 1
ELSE 1
END
) = 1
GROUP BY BROWSER_TYPE, BROWSER_VERSION, ERROR_CODE;
以下為本次查詢SQL的重點。
- 使用
CASE..WHEN..ELSE..END
把不屬於主流瀏覽器的名稱或null改為OTHERS
。 - 使用
WHERE
搭配AND ( CASE..WHEN..ELSE..END ) = 1
來排除不需要統計的瀏覽器版本。 - 把毫秒單位轉成日期做為查前一天記錄的查詢條件。
- 使用
GROUP BY
統計各瀏覽器,各版本,各錯誤代碼的次數總計。 - 使用子查詢的原因是其他瀏覽器名稱轉成的
OTHERS
與null轉成的OTHERS
不會被聚合在同一類,所以要先用子查詢轉換後再用GROUP BY
聚合。
參考:
沒有留言:
張貼留言