Как извлечь записи в SAS PRO C SQL passthru, отфильтрованные по дате, но дата в строковом формате? - PullRequest
1 голос
/ 28 февраля 2020

Я пытаюсь извлечь данные из диапазона дат (устанавливается переменными start_date и end_date, определенными в нулевом шаге).

Обычно я делаю это, используя passthru PRO C 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;

Это извлекает данные гораздо более эффективно, чем выполнение их через шаг данных или извлечение всех данных и их фильтрация.

Проблема связана с этим конкретным набором данных. с использованием даты и времени сохраняется в виде строки в формате «ДД / ММ / ГГГГ ЧЧ: ММ: СС». Я знаю, как преобразовать это обычно в шаге данных или тому подобное, но проблема в том, что я не могу преобразовать или интерпретировать его как дату на промежуточной стадии PRO C SQL.

Замена шага WHERE с любой функцией SAS, как показано ниже, выдается «Oracle Prepare Error», поскольку она не распознает функции. Я также пытался использовать функции SQL для чего-то похожего в прошлом, и они также не работали, и мне не удалось найти решение.

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

Возможно ли интерпретировать строку как datetime в промежуточной стадии и использовать его для фильтрации? Или, может быть, есть другой способ сделать это, который все еще более эффективен, чем вытягивание всего или выполнение шага данных непосредственно на данные oracle?

Ответы [ 2 ]

2 голосов
/ 28 февраля 2020

Когда вы проходите через критерии даты к 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'

При проходе используются макропеременные 'literal'

WHERE date >= &ora_start_literal. AND date <= &ora_end_literal;
0 голосов
/ 28 февраля 2020

Мы используем форматы для упрощения процесса.

Создайте формат с именем 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'''.

Как показывает Ричард, хорошей практикой является сохранение дат / дат / времени в виде значений даты / даты SAS, чтобы вы могли работать с ними, а затем создание дополнительных переменных для использования в операторе passthrough.

...