Я не могу понять, как правильно искать (SAS) - PullRequest
0 голосов
/ 11 декабря 2018

В Base SAS у меня есть скрипт с хеш-объектом для поиска в таблице.Условие как следовать.Таблица A - это исходная первичная таблица, которая будет использовать таблицу B для поиска.Ключ поиска - AssetName и Voltage.Напряжение всегда равно 33 или 11.

Итак, теперь мы можем себе представить, что это поиск в таблице A с помощью таблицы B с использованием AssetName и Voltage для получения некоторых данных из таблицы B.

Позволяет получитьпосмотрите на пример кода, который у меня есть.

data ncpdm.ncp_load_re (drop=excp_code re_state re_supply_zone)
     work.excp_ncp_load_re;
  length excp_code $50 re_state re_supply_zone $30;

  if _n_=1 then do;
     declare hash pmu_list(dataset:"ncpdm.ncp_asset_pmu");
     pmu_list.definekey('assetname','voltage');
     pmu_list.definedata('region','zone','state_code','state',
                         'business_area_code','business_area',
                         'supply_zone_code','supply_zone',
                         'sub_supply_zone_code','sub_supply_zone',
                         'pmu_name','substation_name_tnbt','functional_location');
     pmu_list.definedone();
     call missing(region,zone,state_code,state,
                  business_area_code,business_area,
                  supply_zone_code,supply_zone,
                  sub_supply_zone_code,sub_supply_zone,
                  pmu_name,substation_name_tnbt,functional_location);
  end;
  set asset_re (RENAME=(pmu=assetname voltage=voltage_));
  data_dttm=datetime();

  voltage_=strip(voltage_);
voltage=cats('132/',voltage_);
mnemonic_tnbt=strip(mnemonic_tnbt);
 assetname=mnemonic_tnbt;


  rc=pmu_list.find();
  if (rc^=0) then do;
     excp_code='Exception: Mnemonic_tnbt and Voltage not mapped to PMU master list';
     output work.excp_ncp_load_re;
  end;
  else do;
  output ncpdm.ncp_load_re;
  end;

  keep mnemonic_tnbt excp_code re_state re_supply_zone
       region zone state_code state business_area_code business_area
       supply_zone_code supply_zone sub_supply_zone_code sub_supply_zone
       pmu_name substation_name_tnbt functional_location voltage
       re_state
re_station
re_ca_no
re_customer_name
re_capacity
re_commission_date
re_technology
pmu
ppu
ssu_pe
re_switch_no
voltage

period
 data_dttm
 active_flag                    
program             
scod_date               
kick_off_date       
iom_date
geo_longitude
geo_latitude;
run;

Из моего кода выше, я установил те, которые не могут быть сопоставлены / поиск для вывода в таблицу исключений.Затем я использую тот же объектный код хеша, но с excp в качестве источника данных, чтобы снова найти ту же таблицу, код как показано ниже.(Я изменяю Напряжение на 33 или 11 (противоположно существующему напряжению).

/*2nd round lookup for failed record*/
data ncpdm.ncp_load_rev2 (drop=excp_code re_state re_supply_zone)
     work.excp_ncp_load_re (drop=excp_code re_state re_supply_zone);
  length excp_code $50 re_state re_supply_zone $30;

  if _n_=1 then do;
     declare hash pmu_list(dataset:"ncpdm.ncp_asset_pmu");
     pmu_list.definekey('assetname','voltage');
     pmu_list.definedata('region','zone','state_code','state',
                         'business_area_code','business_area',
                         'supply_zone_code','supply_zone',
                         'sub_supply_zone_code','sub_supply_zone',
                         'pmu_name','substation_name_tnbt','functional_location');
     pmu_list.definedone();
     call missing(region,zone,state_code,state,
                  business_area_code,business_area,
                  supply_zone_code,supply_zone,
                  sub_supply_zone_code,sub_supply_zone,
                  pmu_name,substation_name_tnbt,functional_location);
  end;
  set work.excp_ncp_load_re;
  data_dttm=datetime();

  if voltage='132/11' then voltage = '132/33';
  else if voltage='132/33' then voltage='132/11';

mnemonic_tnbt=strip(mnemonic_tnbt);
  assetname=mnemonic_tnbt;
re_state=state;
re_station=station;
re_ca_no=ca_no;
re_customer_name=applicant_name;
re_capacity=capacity;
re_commission_date=commission_date;
re_technology=technology;

geo_latitude=lat;
geo_longitude=lng;

  rc=pmu_list.find();
  if (rc^=0) then do;
     excp_code='Exception: Mnemonic_tnbt and Voltage not mapped to PMU master list';
     output work.excp_ncp_load_re;
  end;
  else do;
  output ncpdm.ncp_load_rev2;
  end;

  keep mnemonic_tnbt excp_code re_state re_supply_zone
       region zone state_code state business_area_code business_area
       supply_zone_code supply_zone sub_supply_zone_code sub_supply_zone
       pmu_name substation_name_tnbt functional_location voltage
       re_state
re_station
re_ca_no
re_customer_name
re_capacity
re_commission_date
re_technology
pmu
ppu
ssu_pe
re_switch_no
voltage

period
 data_dttm
 active_flag                    
program             
scod_date               
kick_off_date       
iom_date
geo_longitude
geo_latitude;
run;

Проблема в том, что для тех, у кого нет соответствующего Напряжения в моем первом хэш-объекте, мне удалось найти во второмКод хеш-объекта, НО я все еще получаю не отображенные записи. Как только я добавляю таблицу, сгенерированную из 1-го хеш-объекта и 2-го хеш-объекта, я все равно получаю меньше записей, чем желаемый результат.

Я не мог понять, как применитьлучшая логика. Почему-то я чувствую, что мой метод использования 2-го хеш-объекта для поиска не является необходимым, но я просто не знаю, как лучше.

Есть ли лучший способ для этого?

1 Ответ

0 голосов
/ 12 декабря 2018

Вы можете выполнить оба поиска за один шаг.После первого сбоя find() измените значение key2 на его альтернативное значение и выполните другое find().Примечание. Для случаев, когда совпадений не обнаружено, спутниковые переменные поиска должны быть явно установлены как отсутствующие, чтобы выходной набор данных был точным - если не сбросить, переменные поискового спутника будут содержать значения из самого последнего предыдущего совпадения.

Пример кода:

В этом примере создаются данные для основной таблицы и таблицы поиска.Каждая таблица имеет несколько спутниковых переменных, которые должны быть перенесены в наборы выходных данных.Также создается переменная состояния, указывающая тип совпадения или несоответствия.

data have(keep=key1 key2 have:);
  length key1 $6 key2 $2;
  do _n_ = 1 to 5000;
    key1 = repeat(byte(26*ranuni(123)+rank('A')),5);
    key2 = ifc(ranuni(123) < 0.35, '11', '33');
    if ranuni(123) < 0.02 then key2 = '22';
    array have(3); * satellite (non-key) variables in have;
    do i = 1 to 3;
      have(i) = _n_ * 10000 + i;
    end;
    output;
  end;
  format have: 8.;
run;

data lookup(keep=key1 key2 look:);
  length key1 $6 key2 $2;
  array look(5); * satellite (non-key) variables in lookup;
  do i = 1 to 26;
    key1 = repeat(byte(i-1+rank('A')),5);
    array key2s(2) $2 _temporary_ ('11','33');
    do j = 1 to 2;      
      key2 = key2s(j);
      do k = 1 to 5;
        look(k) = i * 1000 + j * 100 + k;
      end;
      if ranuni(123) < 0.40 then output;
    end;
  end;
  format look: 8.;
run;

data match no_match;

  length key1 $6 key2 $2 match_status $30;

  if _n_ = 1 then do;

    if 0 then set lookup; * prep pdv at compilation time, set is never executed at runtime;

    declare hash lookup(dataset:'lookup');
    lookup.defineKey('key1', 'key2');
    do i = 1 to 5; drop i;
      lookup.defineData(cats('look',i));
    end;
    lookup.defineDone();
  end;

  set have;

  rc = lookup.find();

  if rc = 0 then do;
    match_status = 'match on actual keys';
    output match;
    return; * to top of step;
  end;

  * first lookup failed, try the alternate key2;

  if key2 = '11' then 
    key2='33';
  else
  if key2 = '33' then
    key2 = '11';
  else do;
    call missing (of look:); * clear lookup values that find() loaded at last prior match;
    match_status = 'no match, key2 invalid';
    output no_match;
    return; * to top of step;
  end;

  rc = lookup.find();

  if rc = 0 then do;
    match_status = 'match after key2 swap';
    output match;
    return; * to top of step;
  end;
  else do;
    call missing (of look:); * clear lookup values that find() loaded at last prior match;
    match_status = 'no match with 11 or 33';
    output no_match;
    return; * to top of step;
  end;
run;
...