2015-03-06 5 views
2

Я новичок в SAS. Мне нужно сделать x- итерации для заполнения моего набора данных MYRS.Рекурсивно добавить к таблице данных в SAS

Каждая итерация нуждается в РЕГИСТРИРУЙТЕСЬTABLE1 с (TABLE2 + MYRS) МИНУС записей, которые уже в MYRS таблице.

Затем мне нужно обновить таблицу MYRS с дополнительными совпадениями. Цель состоит в том, чтобы отслеживать цепочку писем.

MYRS по существу является копией TABLE1 и содержит соответствующие записи. Какой-то хитрый. (упрощенная схема). Table1 Может иметь DUPS.

Например

TABLE1: 
ID | EMAIL1 | EMAIL2 | EMAIL3 | EMAIL4| 
1 | A | s | d | F 
2 | g | F | j | L 
3 | z | x | L | v 
4 | z | x | L | v 
2 | g | F | j | L 

TABLE2: 
EMAIL 
A 

MYRS (starts as empty dataset) 
EMAIL1 | EMAIL2 | EMAIL3 | EMAIL4 

Логика: TABLE1 имеет электронную почту, которая соответствует по электронной почте в TABLE2. Поэтому эта запись должна появиться. Другие записи ничего не соответствуют в TABLE2. Но так как Record1 и Record2 доля the same ALTERNATIVE emailF, Record2 также должны быть показаны. Но так как Record2 и поделитесь тем же самым альтернативным адресом электронной почты L, Record3 также должен быть показан. И вот четвёртое ...

proc sql;   
SELECT TABLE1.id, 
    TABLE1.email1, 
    TABLE1.email2, 
    TABLE1.email3, 
    TABLE1.email4 
FROM TABLE1 
INNER JOIN (
    SELECT EMAIL 
    FROM TABLE2  
    UNION  
    SELECT EMAIL1 AS EMAIL 
    FROM MYRS 
    UNION  
    SELECT EMAIL2 AS EMAIL 
    FROM MYRS 
    UNION  
    SELECT EMAIL3 AS EMAIL 
    FROM MYRS 
    UNION  
    SELECT EMAIL4 AS EMAIL 
    FROM MYRS 
    ) 
ON EMAIL=EMAIL1 OR EMAIL=EMAIL2 OR EMAIL=EMAIL3 OR EMAIL=EMAIL4 
WHERE TABLE1.id NOT IN (
     SELECT DISTINCT ID 
     FROM MYRS 
     ) 
quit; 

Как я могу создать следующую логику:

  1. Wrap это в какой-то функции
  2. Перед выполнением SQL, подсчитывает количество записей в MYDS и сохранить кол
  3. Выполнить SQL и обновить MYDS
  4. графа количество записей в MYDS
  5. Если MYDS счетчик не изменится, остановить execut ион
  6. Else, Гот # 3

Я новичок в SAS (3 дня, чтобы быть точным) и пытаюсь поставить все вместе. (Я бы использовал вышеприведенную логику, если бы я сделал это на Java)

+0

Возможно, вы могли бы написать макрос, чтобы сделать это так, как вы указали выше, но часть меня говорит, что если вы реструктурируете свои данные, у вас могут быть лучшие варианты. Можете ли вы опубликовать обработанный пример, мне нелегко визуализировать проблему. – Reeza

+0

В зависимости от размера ваших данных хеш-таблицы могут быть хорошими кандидатами для решения этой проблемы. –

ответ

1

Вот макро-подход, он в основном следует вашей логике, но сначала преобразует ваши данные, а вход/выход - это список ID (можно легко добраться до и от писем с этим).

Этот код, вероятно, представит немало функций SAS, с которыми вы не знакомы, но комментарии и объяснения, приведенные ниже, должны помочь. Если какой-либо из них по-прежнему неясен, посмотрите ссылки или добавьте комментарий.

Он ожидает ввода данных:

  • inData: Ваш TABLE1 с ID и EMAIL* переменных
  • matched: первоначальный список известных хотел ID s

возвращает:

  • matched: Обновленный список хотел ID сек

/* Wrap the processing in a macro so that we can use a %do loop */ 
%macro looper(maxIter = 5); 
    /* Put all the emails in one column to make comparison simpler */ 
    proc transpose data = inData out = trans (rename = (col1 = email)); 
     by ID; 
     var email:; 
    run;   
    /* Initialise the counts for the %where condition */ 
    %let _nMatched = 0; 
    %let nMatched = 1; 
    %let i = 0; 
    /* Loop until no new IDs are added (or maximum number of iterations) */ 
    %do %while(&_nMatched. < &nMatched. and &i < &maxIter.); 
     %let _nMatched = &nMatched.; 
     %let i = %eval(&i. + 1); 
     %put NOTE: Loop &i.: &nMatched. matched.; 
     /* Move matches to a temporary table */ 
     proc datasets library = work nolist nowarn; 
      delete _matched; 
      change matched = _matched; 
     quit; 
     /* Get new matched IDs */ 
     proc sql noprint; 
      create table matched as 
      select distinct c.ID 
      from _matched as a 
      left join trans as b 
       on a.ID = b.ID 
      left join trans as c 
       on b.email = c.email; 
      /* Get new count */ 
      select count(*) into :nMatched from matched; 
     quit; 
    %end; 
%mend looper; 
%looper(maxIter = 10); 

Интересные биты:

  • proc transpose: Преобразует вход в глубокую таблицу так, чтобы все адреса электронной почты в одна переменная, это упрощает запись схемы сравнения электронной почты (меньше необходимости повторения) и помещает данные в формат, который облегчит вам очистку адресов электронной почты, если необходимо (подумайте upcase(), strip() и т. Д.).
  • %macro %mend: Операторы, используемые для определения macro. Это необходимо, так как вы не можете использовать макрокоманду или циклы в открытом коде. Я также добавил аргумент, чтобы вы могли видеть, как это работает.
  • %let и select into :: Два способа создания macro variables. Макро-переменные ссылаются на префикс & и используются для вставки текста в программу SAS до его выполнения.
  • %do %while() %end: Один из способов выполнения цикла в макросе. Код внутри будет повторяться до тех пор, пока условие не примет значение false.
  • proc datasets: Процедура выполнения задач администрирования в наборах данных и библиотеках. Используется здесь для удаления и переименования временных таблиц.
Смежные вопросы