Equivalencias entre PROC SQL y DATA en las uniones de tablas SAS

12 Ago

Muchos de los que llegan a programar con SAS son grandes expertos en SQL. Cuando dominas perfectamente un lenguaje es difícil acostumbrarse a otro. Por ello quiero plantear un artículo que estudie los tipos de uniones mediante pasos DATA y su análogo con el PROC SQL. Con ello espero que los profesionales que manejan el lenguaje SQL entiendan mejor el paso DATA. En mi línea habitual creo dos dataset y manejo ejemplos.


data uno;
input anio importe;
cards;
2000 100
2001 200
2002 300
2003 350
2004 375
2005 450
; run;
data dos;
input anio importe2;
cards;
2003 550
2004 775
2005 650
2006 900
2007 450
; run;

Las formas de unir conjuntos de datos SAS son:

Uniones verticales:

Concatenación:

data tresA;
set uno dos;
run;
proc sql;
create table tresB as
select * from uno
outer union corr
select * from dos;
quit;

Intercalación:

data cuatroA;
set uno dos;
by anio;
run;
proc sql;
create table cuatroB as
select * from uno
outer union corr
select * from dos
order by anio;
quit;

Uniones horizontales:

Total:

data cincoA;
merge uno dos;
by anio;
run;
proc sql;
create table cincoB as select
case
when a.anio is null then b.anio
else a.anio end as anio,
*
from uno a full join dos b
on a.anio = b.anio;
quit;

Excluyentes:

Están en ambas tablas:

data seisA;
merge uno (in=en_uno) dos (in=en_dos);
by anio;
if en_uno and en_dos;
run;
proc sql;
create table seisB as select
*
from uno a, dos b
where a.anio = b.anio;
quit;
proc sql;
create table seisC as select
*
from uno a inner join dos b
on a.anio = b.anio;
quit;

Están en la tabla de la izquierda:

data sieteA;
merge uno (in=en_uno) dos (in=en_dos);
by anio;
if en_uno;
run;
proc sql;
create table sieteB as select
*
from uno a left join dos b
on a.anio = b.anio;
quit;

Están en la tabla de la derecha:


data ochoA;
merge uno (in=en_uno) dos (in=en_dos);
by anio;
if en_dos;
run;
proc sql;
create table ochoB as select
case
when a.anio is null then b.anio
else a.anio end as anio,
*
from uno a right join dos b
on a.anio = b.anio;
quit;

No he comentado los ejemplos porque son bastante claros. Como véis en SQL es muy importante el orden en el que se nombran las variables por eso para algunos ejemplos empleamos el CASE, si él el resultado no sería el esperado ya que nos tomaría la variable anio del primer dataset que aparece en la select, para el resto nos pondría valores perdidos, probad los ejemplos sin el case y entenderéis porque lo empleo. En el terreno profesional comentaros que se emplea mucho la INNER JOIN y la LEFT JOIN fundamentalmente cuando unimos 2 datasets con índices y deseamos prescindir de ordenaciones previas por ser muy costosas. Si trabajamos con uniones de más de 2 datasets recomiendo trabajar con MERGE. Es habitual partir de una tabla base y añadirla información de otras en un paso DATA final. Por supuesto si tenéis dudas, más sugerencias o un empleo que me permita estar más tiempo con mi familia que pronto pasará a ser numerosa estoy en rvaquerizo@analisisydecision.es

15 respuestas a «Equivalencias entre PROC SQL y DATA en las uniones de tablas SAS»

  1. No conocía el outer union corr. La verdad es que yo me he acostumbrado a utilizar el método que más intuitivo me resulta en cada caso, y en algunos no conocía el equivalente en el otro método. Hoy precisamente me he llevado una sorpresa cuando he comprobado el funcionamiento del caso «Están en la tabla de la izquierda» cuando hay duplicados:
    data uno;
    anio=1;importe=2;output;
    anio=1;importe=3;output;
    anio=1;importe=4;output;
    run;

    data dos;
    anio=1;importe2=5; output;
    anio=1;importe=6; output;
    run;

    y ejecutar de nuevo los joins.

  2. A ver si tengo tiempo y hago un pequeño análisis de espacio y tiempo con varios tipos de uniones.

    Después de haber trabajado con 1.000 profesionales de SAS distintos (por lo menos) me he dado cuenta de que el SQL no se emplea mucho a excepción de aquellos que vienen del PL.

    A mi particularmente me gusta emplear el SQL porque se entiende mejor y, en ocasiones, es necesario migrar procesos de SAS a Oracle, DB2, Informix,.. y es mejor migrar código SQL.

  3. Hola,chicos. Tengo una duda epro no es sobre este tema. Estoy intentando importar una tabla en excel pero no lo consigo. Pongo este codigo:
    proc export data=Tabla1
    DBMS=Excelcs
    OUTFILE=’C:Victor\Tabla.xls’ replace;
    SERVER=»xxx.xx.xx.xx»;
    PORT=yyyy;
    VERSION=’2000′;
    SHEET=»Hoja1″;
    run;
    Pero me da errores de escritura pero no se cual es. Gracias

  4. Perdon, el codigo es este:
    proc import datafile = «C:\Victor\Tabla.xls»
    OUT=kk;
    DBMS=Excelcs
    SERVER=’xxx.xx.xx.xx’;
    PORT=yyyy;
    VERSION=’2000′;
    SHEET=’Hoja1′;
    run;

  5. Si, tengo la tabla en el servidor y estaba intentando importarla,pero ya lo conseguí. El código es el siguiente:

    proc import DBMS=excelcs
    datafile = ‘C:\victor\tabla.xls’
    OUT=work.tabla1;
    SERVER=»xxx.xx.xx.xx»;
    PORT=yyyy;
    SHEET=»Hoja1″;
    run;

    Me he dado cuenta de que los proc import y export dan errores si se colocan las opciones de cierta manera.
    Espero que sirva de ayuda este ejemplo

  6. Hola! Les escribo para pregunarles como puedo hacer un código en sas para comparar dos coulumnas de un mismo archivo de datos y condiconales si las columnas son iguales o doferentes.
    Gracias

  7. Hola,
    Tengo una duda como unes dos BBDD por dos variables?
    En este caso seria por paciente y por anio.
    Suponiendo que tienes estas la BBDD uno y dos:
    data uno;
    input paciente anio importe;
    cards;
    1 2000 100
    1 2001 200
    2 2001 300
    2 2002 350
    3 2000 375
    3 2002 450
    ; run;
    data dos;
    input paciente anio importe2;
    cards;
    1 2000 550
    1 2001 775
    1 2002 650
    2 2000 900
    3 2001 450
    ; run;

    que como resultado tengas tres de la siguiente manera:

    paciente anio importe importe2
    1 2000 100 550
    1 2001 200 775
    1 2002 650
    2 2000 900
    2 2001 300
    2 2002 350
    3 2000 375
    3 2001 450
    3 2002 450

  8. Hola Aitor, te dejo una forma de hacerlo. La tercera tabla es la unión de tus bases uno y dos; la cuarta tabla es el resultado como lo requieres, espero te sirva.
    Saludos
    PROC SORT DATA=UNO;
    BY PACIENTE ANIO;
    RUN;

    PROC SORT DATA=DOS;
    BY PACIENTE ANIO;
    RUN;

    DATA TRES;
    MERGE UNO (IN=A) DOS (IN=B);
    BY PACIENTE ANIO;
    RUN;

    DATA CUATRO;
    SET TRES;
    IF IMPORTE = . THEN DO;
    IMPORTE = IMPORTE2;
    IMPORTE2 = .;
    END;
    RUN;

  9. Hola, me podrian ayudar, necesito seleccionar los primeros 160 pacientes tomando como referencia la fecha de inicio que es rdmdt que sea antes del 6 de enero 2014

  10. Buenos días,
    Estoy intentando crear un bucle dentro de una macro que me junte todas las tablas que he creado en un paso anterior, pero el problema es que el número de tablas que se crean (y que son las que quiero anidar) es variable y al hacerlo así, la última me solapa las anteriores.

    La macro variable total_tablas es variable.
    Tengo ‘total_tablas’ tablas creadas en cada caso (que se llaman tabla_1, tabla_2, tabla_3, …) que quiero anidar en una unica tabla que se llame ‘tabla_todo’

    %do r=1 %to &total_tablas.;
    data tabla_todo;
    set tabla_&r.;
    run;
    %end;

    Muchas gracias de antemano.

  11. Hola Naiara,
    No sé si te servirá lo que voy a decirte, pero intenta poniendo:

    data tabla_todo;
    set tabla_:;
    run;

    Con esta opción te juntará en el data tabla_todo todos los datas que empiecen por «tabla_».

    Espero que te sea de ayuda.
    Un saludo,
    Kike

  12. Buenos días! Primero de tood muchas gracias por la información de la página!
    Ahí va mi problemilla asolucionar:
    Tengo una tabla con tres columnas. Una es la fecha de una propuesta, la otra es el tipo de propuesta hecha y la última es el nif de la persona que hace la propuesta.
    Quiero obtener la propuesta (de cada tipo de propuesta) más reciente que ha hecho cada persona. Es decir, querría agrupar la información por NIF y tipo de propuesta: si una persona ha hecho una propuesta del tipo A, dos del B y una del C; obtendré 3 registros de esa persona: una propuesta del tipo A, otra del B y otra del C.
    Cuando hay más de un registro del mismo tipo de propuesta de la misma persona, es porque hay fechas diferentes. Querría obtener la fecha más reciente de cada uno de estos registro. En el ejemplo, los registros que “quedarían” sería la propuesta del tipo A, la propuesta del tipo B más reciente y la propuesta del tipo C.
    En acces esto se hace agrupando los campos tipo propuesta y NIF, y obteniendo el max de fecha de propuesta. He intentado hacer lo mismo en SAS, pero al maximizar la fecha solo me da el días más reciente y no el más reciente de los campos con NIF duplicados.
    Sería posible realizar esto con SAS?
    Muchas gracias y un saludo,

  13. Hola, alguien sabe como dejar en proc import las » como delimitador, he intentado:

    proc import datafile=»C:\Temp\archivo.txt»
    dbms=dlm
    out=mydata
    replace;
    delimiter= ‘»‘; /*Aqui coloque las comillas pero no funciona con ‘&’ funciona pero no es lo que necesito */
    getnames=yes;
    run;

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *