如何在SAS自定义函数中访问表值并获取SQL查询返回值?
在SAS EG中实现带银行假日的月度工作日函数
核心思路
在SAS的FCMP自定义函数中直接嵌入PROC SQL,通过SELECT INTO语句将查询结果赋值给函数的局部变量,再用这些变量完成最终的工作日计算;如果需要返回多个值,可通过输出参数实现。
代码实现示例
假设你的银行假日表名为bank_holidays,包含日期列holiday_date,以下是完整的函数定义:
1. 单返回值函数(返回工作日天数)
/* 创建函数并存储到work.funcs库 */ PROC FCMP OUTLIB=work.funcs.day_calc; /* 输入参数:指定日期(用来确定统计的月份),返回值为数值型 */ FUNCTION calc_month_workdays(input_date DATE) RETURNS NUMERIC; /* 声明存储SQL结果的局部变量 */ DECLARE num holiday_count; DECLARE num month_start; /* 用SQL获取当月已过的银行假日数量,以及当月起始日期 */ PROC SQL NOPRINT; SELECT COUNT(holiday_date), INTNX('MONTH', input_date, 0, 'BEGINNING') INTO :holiday_count, :month_start FROM bank_holidays WHERE holiday_date BETWEEN :month_start AND input_date; QUIT; /* 计算当月已过的总天数 */ DECLARE num passed_days; passed_days = input_date - month_start + 1; /* 计算当月已过的周末天数 */ DECLARE num weekend_days; weekend_days = 0; DO i = month_start TO input_date; IF WEEKDAY(i) IN (1,7) THEN weekend_days = weekend_days + 1; END; /* 计算最终工作日天数 */ DECLARE num work_days; work_days = passed_days - weekend_days - holiday_count; RETURN work_days; ENDSUB; RUN; /* 注册函数库,让SAS能识别自定义函数 */ OPTIONS CMPLIB=work.funcs;
2. 带输出参数的函数(返回工作日天数+银行假日数)
如果需要同时返回银行假日数量等额外值,可通过OUTARGS定义输出参数:
PROC FCMP OUTLIB=work.funcs.day_calc; /* OUTARGS后声明输出参数,函数仍返回工作日天数 */ FUNCTION calc_month_workdays(input_date DATE, OUTARGS holiday_count NUMERIC) RETURNS NUMERIC; DECLARE num month_start; PROC SQL NOPRINT; SELECT COUNT(holiday_date), INTNX('MONTH', input_date, 0, 'BEGINNING') INTO :holiday_count, :month_start FROM bank_holidays WHERE holiday_date BETWEEN :month_start AND input_date; QUIT; /* 计算周末天数与工作日天数 */ DECLARE num passed_days weekend_days work_days; passed_days = input_date - month_start + 1; weekend_days = 0; DO i = month_start TO input_date; IF WEEKDAY(i) IN (1,7) THEN weekend_days = weekend_days + 1; END; work_days = passed_days - weekend_days - holiday_count; RETURN work_days; ENDSUB; RUN; OPTIONS CMPLIB=work.funcs; /* 使用示例 */ DATA test; target_date = TODAY(); /* 调用函数,同时获取工作日天数和银行假日数 */ work_days = calc_month_workdays(target_date, holiday_count); PUT "截至" target_date DATE9. ",当月工作日:" work_days "天,银行假日:" holiday_count "天"; RUN;
关键注意事项
- 确保银行假日表的库路径正确,若表不在work库,需在SQL中指定完整库名(如
lib.bank_holidays)。 PROC SQL需加NOPRINT参数,避免查询结果输出到日志。- 局部变量必须先用
DECLARE声明,否则无法被SQL赋值。
内容的提问来源于stack exchange,提问作者CaptainFuzzyFace
相关产品推荐
相关产品推荐

