Заполнить макропеременную SAS с помощью инструкции SQL в другой инструкции SQL?

Я наткнулся на следующий фрагмент кода, в котором переменная top3 должна быть заполнена из таблицы have, а не из массива чисел.

%let top3 = 14 15 42; /* This should be made obsolete.. */
%let no = 3;

proc sql;
   create table want as
   select *
   from (select x, y from foo) a
   %do i = 1 %to &no.;
     %let current = %scan(&top3.,&i.);   /* What do I need to put here? */
     left join (select x, y from bar where z=&current.) row_&current.
     on a.x = row_&current..x
   %end;
   ;
quit;

Таблица have содержит xs из строки и выглядит следующим образом:

i   x
1   14
2   15
3   42

Теперь мне интересно, как мне изменить строку %let current = ..., чтобы current заполнялась из таблицы have. Я знаю, как заполнить переменную макроса, используя proc sql с select .. into, но я боюсь, что то, как я сейчас поступаю, полностью противоречит философии SAS.

Почему в исходном запросе используется цикл %DO, а не просто select x, y from bar where z in (&top3)? У вас не может быть более одной переменной с именем Y, вы упростили свой пример?

Tom 09.12.2020 23:42
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
1
153
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

Пример:

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

data masters;
  call streaminit(2020);

  do id = 1 to 100;
    do x = 1 to 100;
      m_rownum + 1;
      code = rand('integer', 10,45);
      output;
    end;
  end;
run;

data details;
  call streaminit(2020);
  do date = 1 to 20;
    do x = 1 to 100;
      do rep = 1 to 5;
        d_rownum + 1;
        amount = rand('integer', 100,200);
        z = rand('integer', 10,45);
        output;
      end;
    end;
  end;
run;

data zs;
input z @@; datalines;
14 15 42
;

proc sql;
  create table want as
  select
    m_rownum
  , d_rownum
  , masters.id
  , masters.x
  , masters.code
  , details.z
  , details.date
  , details.amount
  from
    masters
  left join 
    details
  on
    details.x = masters.x
  inner join
    zs
  on 
    zs.z = details.z
  order by
    masters.id, masters.x, details.z, details.date
  ;
  quit;
Ответ принят как подходящий

Похоже, вы более или менее что-то транспонируете. Если это так, это довольно легко выполнимо в макросе/sql.

Во-первых, вот простая версия - без макроса.

proc sql;
  create table class_t as
  select * from (
    select name from sashelp.class ) class
        left join (
          select name, age as age_Alfred
          from sashelp.class 
          where name='Alfred') Alfred
          on class.name = Alfred.name
  ;
quit;

Мы берем значение age из строки Alfred и помещаем его в основное соединение. Это не совсем то, что вы делаете, но похоже. (Я использую только одну таблицу, но вы, конечно, можете использовать две.)

Теперь, как мы можем расширить это, чтобы оно управлялось таблицей, а не писалось от руки? Макросы!

Во-первых, вот макрос — просто взять бит Альфреда и сделать его универсальным.

%macro joiner(name=);
    left join (
          select name, age as age_&name.
          from sashelp.class 
          where name = "&name.") &name.
          on class.name = &name..name
%mend joiner;

Во-вторых, мы смотрим на это и видим две вещи, которые нам нужно поместить в списки макросов: список переменных SELECT (мы будем получать одну новую переменную для каждого вызова) и список JOIN.

proc sql;
  select cats('%joiner(name=',name,')')
    into :joinlist separated by ' '
    from sashelp.class;
  select cats(name,'.age_',name)
    into :selectlist separated by ','
    from sashelp.class;   
quit;

И тогда, мы просто называем это!

proc sql;
  create table class_t as
    select class.name,&selectlist. from (
        select name from sashelp.class) class
        &joinlist.
    ;
quit;

Теперь ваш набор данных, из которого вы вызываете списки макросов, возможно, представляет собой набор данных с тремя строками, которые у вас есть выше («есть»). Набор данных, из которого вы на самом деле получаете присоединяемые данные, — это какой-то другой набор данных («полоса»), верно? И затем те, к которым вы присоединяетесь, возможно, являются третьим набором данных («foo»). Здесь я просто использую один, для простоты, но концепция та же, просто разные источники.

Я не понимаю, как &selectlist. может быть правильно заполнен вашим кодом. Я ожидаю, что будет (только в случае Alfred) быть Alfred.age_Alfred и полным соединением, которое возвращает ваш макрос %joiner(). Я что-то упускаю из виду?

B--rian 10.12.2020 10:39

Другие вопросы по теме