Преобразование запроса Proc Sql Exists в шаг данных

У меня есть этот запрос proc sql в моем текущем коде. К сожалению, я имею дело с более чем 10 миллионами записей, поэтому на выполнение уходит несколько часов. Я пытался преобразовать его в шаг данных, думая, что он будет работать намного быстрее. Тем не менее, я не могу получить те же результаты данных. Если кто-нибудь может помочь мне с шагом данных, я был бы очень признателен. Или, если у вас есть предложения о том, как я могу сделать proc sql более эффективным.

Вот мой запрос proc sql:

proc sql;
  create table test as
  select *
  from table1 a
  where exists (select 1
                from table2 b
                where b.acct_id = a.acct_id);
quit;

Это шаг данных, в который я пытался преобразовать его:

proc sort data=table1; by acct_id; run;
proc sort data=table2; by acct_id; run;

data test;
  merge table1   (in=a)
        table2   (in=b);
  by acct_id;
  if a and b;
run;

person UncleCross    schedule 11.04.2016    source источник
comment
select * from table1 where acct_id in (select acct_id from table2) работает быстрее? (Этот запрос может сделать намерение более понятным для планировщика запросов - надеюсь, избавит от необходимости индексации/сортировки/объединения)   -  person Jon Clements♦    schedule 11.04.2016
comment
По крайней мере, в SAS 9.3 proc sql довольно плохо оптимизирует операторы IN/EXIST.   -  person Jetzler    schedule 11.04.2016
comment
Я только что провел небольшой тест с вашим предложением, и он показался значительно быстрее (11 минут против 32 секунд). Сейчас попробую полный цикл, посмотрим что получится.   -  person UncleCross    schedule 11.04.2016


Ответы (2)


Попробуйте внутреннее соединение в SQL. Вам нужно будет перечислить каждую переменную, которая должна совпадать.

create table test as
select *
    from
        table1 as a
      inner join
        table2 as b
      on a.acct_id = b.acct_id
      and a.var1 = b.var2 
        ....
      ;

Это должно избежать того внутреннего выбора, на который, как я подозреваю, тратится ваше время.

Если это слишком медленно, рассмотрите возможность добавления индекса для acct_id в обеих таблицах. Это должно ускорить соединение.

person DomPazz    schedule 11.04.2016
comment
Пока table2 помещается в память сеанса, это приведет к хеш-соединению, как и при использовании хэш-таблицы с шагом данных. Должно быть самое быстрое решение. - person Jetzler; 11.04.2016

Что касается того, почему ваш текущий шаг данных не работает, скорее всего, потому, что у вас есть дубликаты ключей в таблице 2 (что исказит наблюдения, где есть слияние 1-N или NN). Если вы измените сортировку, чтобы сохранить только ключи и удалить дубликаты, слияние должно дать ожидаемые результаты.

proc sort data=table1; by acct_id; run;
proc sort data=table2 (keep=acct_id) out=wanted_accounts nodupkey; by acct_id; run;

data test;
merge table1 (in=a)
      wanted_accounts (in=b);
by acct_id;
if a and b;
run;
person Jon Clements♦    schedule 11.04.2016