`DECODE(expr, search1, result1, ..., default)` 相當於 `CASE WHEN expr=search1 THEN result1 ... ELSE default END`,常用於將代碼轉換為描述、薪資分級調整等邏輯。
-- Oracle 範例:薪資調整
SELECT empno, ename, sal,
DECODE(sign(sal - 8000), -1, sal*1.2, 1, sal*1.15, sal*1.15) new_sal
FROM emp;
SAS 無內建 DECODE,但可用宏模擬其語法:`%decode(欄位, 值1, 結果1, 值2, 結果2, ..., 預設值)`。
%MACRO decode / PARMBUFF;
%LOCAL i count ifn valuen countall currfield valueelse;
%LET countall = %SYSFUNC(COUNTW(&SYSPBUFF, %STR(,)));
%LET count = %EVAL((&countall - 1) / 2);
%LET currfield = %SCAN(%QUOTE(&SYSPBUFF), 1);
CASE &currfield
%DO i = 1 %TO &count;
%LET ifn = %SCAN(%QUOTE(&SYSPBUFF), %EVAL(&i * 2));
%LET valuen = %SCAN(%QUOTE(&SYSPBUFF), %EVAL(&i * 2 + 1));
WHEN &ifn THEN &valuen
%END;
%IF %EVAL(&countall > (&count + 1)) %THEN %DO;
%LET valueelse = %SCAN(%QUOTE(&SYSPBUFF), &countall);
ELSE &valueelse
%END;
END
%MEND decode;
PROC SQL;
CREATE TABLE test AS
SELECT
%decode(sex, "M", 0, "F", 1, 2) AS gender_code
FROM sashelp.class;
QUIT;
對應 Oracle:`DECODE(sex, 'M', 0, 'F', 1, 2)`。
PARMBUFF 選項讓宏接收完整參數字串至自動變數 &SYSPBUFF。COUNTW 計算逗號分隔的引數總數(含欄位名)。原版 DECODE 僅支援等值比較。若需區間(如薪資分級),可擴充宏參數格式:
%MACRO decode_range / PARMBUFF;
/* 參數格式: 欄位, 條件1, 結果1, 條件2, 結果2, ..., 預設
條件可為: "GT 8000", "LE 5000", "BETWEEN 3000 AND 8000" 等 */
/* 實作略,核心邏輯同 PARMBUFF 解析,產生 CASE WHEN 條件 THEN 結果 */
%MEND;
| 優點 | 限制 |
|---|---|
| 語法與 Oracle DECODE 高度相似,移植成本低 | 僅支援等值比較,複雜條件需改寫 CASE WHEN |
| 可在 PROC SQL、DATA Step 直接使用 | 巨大引數清單可能超過宏變數長度限制 (64K) |
| 編譯期展開,執行效能等同原生 CASE WHEN | 除錯較難,建議加 `%PUT` 列展開後程式碼 |
以 SAS 宏封裝 `PARMBUFF` 解析邏輯,可在 SAS 環境中以近乎 Oracle `DECODE` 的語法撰寫條件邏輯,大幅降低跨平台遷移的程式碼改寫量。對於複雜條件,建議直接使用原生 `CASE WHEN` 保持可讀與維護性。