如何提取SAS PROC SQL直通中的记录,按日期过滤,但日期为字符串格式



我正在尝试从日期范围(由null步骤中定义的start_date和end_date变量设置(中提取数据。

通常我会使用passthrough PROC SQL来完成此操作,如下所示:

PROC SQL;
CONNECT TO ORACLE AS xxxxx (AUTHDOMAIN="xxxxx" PATH=xxxxx preserve_comments);
CREATE TABLE 
work.new_data AS
SELECT 
*
FROM 
CONNECTION TO xxxxx (SELECT /*+parallel(16)*/ var1, var2, var3
FROM
oracle_data
WHERE date >= &start_date. AND date <= &end_date.);
DISCONNECT FROM xxxxx;
QUIT;

这比通过数据步骤或提取所有数据然后过滤数据更有效地提取数据

问题是,我使用的这个特定数据集的日期时间存储为字符串,格式为"DD/MM/YYYY HH:MM:SS"。我知道如何在数据步骤中正常转换,但问题是我无法在PROC SQL passthrough阶段将其转换或解释为日期。

用下面这样的任何SAS函数替换WHERE步骤都会引发"Oracle准备错误",因为它无法识别这些函数。我过去也尝试过将SQL函数用于类似的事情,但它们也不起作用,我也没能找到解决方案。

WHERE DATEPART(INPUT(rtp_date,anydtdtm.)) >= &start_date.)

是否可以在passthrough阶段将字符串解释为datetime并将其用于筛选?或者,有没有其他方法可以做到这一点,它仍然比提取所有内容或直接在oracle数据上执行数据步骤更有效?

当您将日期条件传递给Oracle时,服务器端日期文本的一个构造实际上是

DATE 'yyyy-mm-dd'

对于用源代码填充宏变量的任务,该源代码是日期文字的Oracle源代码,您需要解释SAS日期时间字符串,检索日期部分并将该值呈现为Oracle日期文字。

示例:

options nosource;
data have;
length task start_date_string end_date_string $19;
input task start_date_string&  end_date_string&;
datalines;
task1  31/01/2020 08:09:10  02/02/2020 11:00:00
task2  15/03/2019 02:00:00  19/03/2019 23:00:00
;
proc sql noprint;
select start_date_string, end_date_string into :start_date, :end_date 
from have where task='task1';
%put &=start_date;
%put &=end_date;
%let s_datepart_val = %sysfunc(inputn(&start_date,ddmmyy10.));
%let e_datepart_val = %sysfunc(inputn(&end_date,ddmmyy10.));
%put &=s_datepart_val;
%put &=e_datepart_val;
%let ora_start_literal = DATE %str(%')%sysfunc(putn(&s_datepart_val,yymmdd10.))%str(%');
%let ora_end_literal   = DATE %str(%')%sysfunc(putn(&e_datepart_val,yymmdd10.))%str(%');
%put &=ora_start_literal;
%put &=ora_end_literal;
---------- LOG ----------
START_DATE=31/01/2020 08:09:10
END_DATE=02/02/2020 11:00:00
S_DATEPART_VAL=21945
E_DATEPART_VAL=21947
ORA_START_LITERAL=DATE '2020-01-31'
ORA_END_LITERAL=DATE '2020-02-02'

以及填充包含日期文字的宏变量的另一种方法;

proc sql noprint;
select
'DATE ' || quote(put(input(start_date_string,ddmmyy10.),yymmdd10.),"'")
, 'DATE ' || quote(put(input(  end_date_string,ddmmyy10.),yymmdd10.),"'")
into
:ora_start_literal
, :ora_end_literal
from
have
where
task = 'task2'
;
%put &=ora_start_literal;
%put &=ora_end_literal;
---------- LOG ----------
ORA_START_LITERAL=DATE '2019-03-15'
ORA_END_LITERAL=DATE '2019-03-19'

传递将使用"文字"宏变量

WHERE date >= &ora_start_literal. AND date <= &ora_end_literal;

我们使用格式来简化流程。

创建一个名为oracledt.的格式,该格式采用日期时间值并将其转换为'mm/dd/yy hh:mm:ss'格式(包括引号(。

proc format lib=work;
picture oracledt low-high = '''%0m/%0d/%y %0H:%0M:%0S''' (datatype = datetime) ;
run ;

创建一个名为my_datetime的宏变量,该变量包含使用上述自定义格式格式化的当前日期时间:

%let my_datetime = %sysfunc(datetime(), oracledt.);
%put &=my_datetime;

输出:

MY_DATETIME='02/28/20 09:13:17'

本白皮书介绍了在构建自己的自定义格式时可以使用的各种值:http://www2.sas.com/proceedings/forum2007/026-2007.pdf

如果您想要的格式是'yyyy-mm-dd hh:mm:ss',那么您的格式定义将如下所示:'''%Y-%0m-%0d %0H:%0M:%0S'''

正如Richard所展示的,将日期/日期时间存储为SAS日期/日期时值是一种很好的做法,这样您就可以使用它们,然后创建用于passthrough语句的其他变量。

最新更新