Что на самом деле делает SAS '/ unique' в операторе set? - PullRequest
1 голос
/ 07 мая 2020

У меня есть старый код SAS, который нужно преобразовать в python.

Часть кода эффективно делает следующее:

data A (index=(key1=(record_id, record_version)));
  set table.xxx (where = ...)
run;

data B;
  set table.yyy (where = ...)
  set A key=key1/unique;
    if _ERROR_ = 1 then do;
      valueA = "";
      _ERROR_ = 0;
    end;
run;

Я прочитал документацию по SET и UNIQUE , в которых говорится:

По умолчанию SET начинает поиск в верхней части индекса только при изменении значения KEY =.

Если значение KEY = не меняется при последовательном выполнении оператора SET, поиск начинается с последующего полученного наблюдения. Другими словами, когда появляются последовательные повторяющиеся значения KEY =, оператор SET пытается однозначно сопоставить повторяющиеся индексированные значения в считываемом наборе данных. Если указано больше последовательных повторяющихся значений KEY =, чем существует в считываемом наборе данных, дополнительные дубликаты рассматриваются как не найденные.

Когда KEY = является уникальным значением, только первая попытка чтения наблюдение с этим ключевым значением успешно; последующие попытки прочитать наблюдение с этим значением ключа терпят неудачу. Переменная IOR C возвращает значение, которое соответствует мнемонике c _DSENOM макроса SYSR C autocall. Если вы добавите параметр / UNIQUE, последующие попытки прочитать наблюдение с уникальным значением KEY = будут успешными. Переменная IOR C возвращает 0.

Ха, «последующие попытки прочитать наблюдение с этим значением ключа терпят неудачу». Как потерпеть неудачу?

Итак, практически говоря, даны A и B:

A record_id record_version valueA     B record_id record_version valueB
  1         1              A11          1         1              B10 
  1         1              A12          1         2              B20
  1         2              A22
  1         3              A33 

Мой вывод обязательно будет включать следующие строки:

record_id record_version valueA valueB
1         1              A11    B10
1         2              A22    B20

Что я не поймите, что делает оператор if _ERROR_.

Получу ли я это?

record_id record_version valueA valueB
1         1                     B10

Или это?

record_id record_version valueA valueB
1         1              A12    B10

Получу ли я это?

record_id record_version valueA valueB
1         3              A33    null

Или это?

record_id record_version valueA valueB
1         3                     null

Какой крайний случай обрабатывает оператор ошибки?

1 Ответ

1 голос
/ 07 мая 2020

Код сбрасывает значение поиска на отсутствующее, когда ключ из данных set table.yyy (where = ...) НЕ присутствует в таблице поиска A. Если сброса не произошло, поисковым значением будет то, что когда-либо было получено из предыдущего успешного поиска.

/UNIUE сообщает SET, что он должен получить первый поиск, если есть более одного возможного поиска (т. е. таблица поиска A имеет повторы record_id / record_version). _ERROR_ по-прежнему требуется для сброса значения поиска в случае, если такой поиск не был найден.

Проблема действительно возникает только в том случае, если в главной таблице больше строк с повторяющимися ключами, чем в уникальная индексированная таблица поиска имеет повторяющиеся ключи.

Пример:

* lookup indexed, but not unique;
* lookup is more typically a 'transaction' table;
data lookup(index=(IDX_key1key2=(key1 key2)));
input key1 key2 valueA $; datalines;
1 1 A11      1st 1 1
1 1 A12      2nd 1 1
1 2 A22
1 3 A33
;

data master;
input key1 key2 valueB $; datalines;
1 1 B10       1st 1 1 
1 2 B20
1 1 B30       1st 1 1 
1 1 B40       2nd 1 1
1 1 B50       3rd 1 1
;

* data for 2nd 1 1 lookup is from 2nd lookup;
* data for 3rd 1 1 lookup is from 2nd lookup and PUT will show _ERROR_=1 in log;
* No _ERROR_ check, that cant be good;
data master_with_keyed_lookup;
  set b;
  set a key=IDX_key1key2;

  put _all_;
run;

* data retrieved for 2nd and 3rd 1 1 lookup are from 1st lookup row due to unique;
* No _ERROR_ check, that cant be good;
data master_with_unique_keyed_lookup;
  set b;
  set a key=IDX_key1key2/unique;

  put _all_;
run;
...