assistant: clara aquí esta el código documentado
//Se crea un nuevo conjunto de datos llamado "salida" que utiliza los datos del conjunto de datos "entrada".
data salida;
    set entrada;
//Se define la longitud de la variable "saldo_recuperado".
   length saldo_recuperado;
 if _N_ = 1 then
  //Se inicia un bloque "do" que se ejecutará solo en la primera iteración del bucle.
 do;
      //Se declara un objeto hash llamado "saldos_rec" que apunta a un subconjunto de datos llamado "saldos_recuperados". El subconjunto se limita a aquellas filas donde la fecha de negociación es menor que "fecha_fv" y mayor o igual a "fecha_iv".
      declare hash saldos_rec(dataset: "saldos_recuperados(where=(&fecha_negocio lt fecha_fv and &fecha_negocio ge fecha_iv))");
      //Se define la clave del objeto hash como "sk_contrato".
      saldos_rec.definekey('sk_contrato');
     // Se definen los datos del objeto hash como "sk_contrato" y "saldo_recuperado".
      saldos_rec.definedata('sk_contrato', 'saldo_recuperado');
     //Se finaliza la definición del objeto hash.
      saldos_rec.definedone();
      //Se llama a la función "missing" para asignar el valor "missing" a la variable "saldo_recuperado".
      call missing(saldo_recuperado);
    end;
    //Se busca la clave en el objeto hash y se almacena el resultado en la variable "rc".
    rc = saldos_rec.find();
    //Se calcula el saldo impagado sumando "saldo_impagado" y el negativo de "saldo_recuperado".
    saldo_impagado=sum(saldo_impagado,-saldo_recuperado)
//se finaliza el buble.
run;
//Se utiliza un procedimiento "sort" para ordenar el conjunto de datos "salida" en orden descendente por la variable "sk_contrato".
proc sort data=salida;
by sk_contrato descending;
run;

prompter: ¡Gracias! Pero ahora me han pedido que lo haga usando solo proc sql, ¿Puedes modificar el codigo para hacer exactamente lo mismo pero solo con proq sql?

assistant: ¡Claro!

Podemos incluirlo en un único proc sql:

proc sql;
    create table salida as     
    select t_entrada.sk_contrato,
           sum(t_entrada.saldo_impagado, -t_saldos.saldo_recuperado) as saldo_impagado
    from entrada as t_entrada
    inner join saldos_recuperados(where=(&fecha_negocio lt fecha_fv and &fecha_negocio ge fecha_iv)) as t_saldos
    on t_entrada.sk_contrato = t_saldos.sk_contrato
    order by sk_contrato desc;
quit;


Básicamente, estamos creando la tabla salida a partir de un left join de la tabla saldos_recuperados (filtrada por los valores de las variables fecha_fv y fecha_iv y la macrovariable fecha_negocio) a la tabla de entrada, y calculando un nuevo saldo_impagado ajustándolo minorando los de la tabla de entrada por los saldo_recuperado.
Si quisieras conservar mas variables de la tabla entrada, deberías añadirlas al select.

También te dejo el código con comentarios, por si lo prefieres:


proc sql;
    create table salida as  /*  Nueva tabla salida       */     
    select t_entrada.sk_contrato,        /*  listamos las variables a conservar de la tabla entrada      */
           sum(t_entrada.saldo_impagado, -t_saldos.saldo_recuperado) as saldo_impagado   /*  calculamos saldo_impagado minorandolo con saldo_recuperado de la tabla entrada      */
    from entrada as t_entrada   /* Indicamos tabla entrada    */     
    inner join saldos_recuperados(where=(&fecha_negocio lt fecha_fv and &fecha_negocio ge fecha_iv)) as t_saldos  /* Indicamos tabla saldos_recuperados, filtrada por los valores de las variables fecha_fv y fecha_iv y la macrovariable fecha_negocio    */  
    on t_entrada.sk_contrato = t_saldos.sk_contrato       /*  realizamos el cruce en función del sk_contrato  */  
    order by sk_contrato desc;  /*  ordenamos la tabla resultante     */     
quit;