SAS9

Cómo cruzar dos tablas sin una clave común

Simon 8 vues

A menudo en la programación SAS©, es necesario cruzar dos conjuntos de datos. Generalmente, usamos una instrucción MERGE en un paso DATA o una unión LEFT/INNER JOIN en SQL a través de una clave común (por ejemplo, un ID de cliente).

Pero, ¿cómo hacerlo cuando las dos tablas no tienen ninguna variable en común y la unión depende de condiciones complejas, como valores comprendidos en intervalos? Esto es lo que se llama una unión no equitativa (Non-Equi Join).

Veamos un caso práctico de una discusión entre usuarios para entender cómo resolver este problema elegantemente con PROC SQL.

La falsa buena idea: el bucle en el paso DATA

Ante este problema, la primera intuición suele ser intentar un enfoque iterativo a través de un paso DATA. La idea sería leer una línea de la tabla accounts, y luego recorrer toda la tabla intervals para encontrar una coincidencia.

Aunque técnicamente es posible, este enfoque es complejo de codificar en SAS©:

  • Requiere manipular dos punteros de lectura.

  • Hay que gestionar el reinicio de la lectura de la tabla intervals para cada cuenta (lo que puede requerir la opción POINT= o múltiples instrucciones SET).

  • El código se vuelve rápidamente pesado y difícil de mantener.

Como señala un colaborador en la discusión: "No perdería tiempo en una metodología de bucle."

La Solución Elegante: PROC SQL y el Producto Cartesiano


La solución más eficaz y legible reside en el uso de PROC SQL. A diferencia del paso DATA, SQL está diseñado para manejar naturalmente las relaciones complejas entre conjuntos sin preocuparse por el orden de clasificación o los bucles explícitos.

El truco consiste en realizar una unión cartesiana (todas las filas de A combinadas con todas las filas de B) y filtrar inmediatamente el resultado.


Note :
Así es como se resuelve el problema en unas pocas líneas:
1PROC SQL;
2 CREATE TABLE DATA3 AS
3 SELECT
4 t1.grpnm,
5 t2.acct,
6 t2.bal1,
7 t2.bal2
8 FROM
9 intervals t1, /* Table 1 */
10 accounts t2 /* Table 2 */
11 WHERE
12 /* Condition pour le premier solde */
13 t2.bal1 BETWEEN t1.min1 AND t1.max1
14 AND
15 /* Condition pour le second solde */
16 t2.bal2 BETWEEN t1.min2 AND t1.max2;
17QUIT;
¿Por qué funciona esto?
FROM data1, data2 : Al listar las dos tablas separadas por una coma sin una cláusula JOIN explícita (como LEFT JOIN), SAS© prepara implícitamente un producto cartesiano. Compara virtualmente cada fila de la tabla intervals con cada fila de la tabla accounts.

WHERE ... BETWEEN : Aquí es donde ocurre la magia. En lugar de usar una igualdad (ON t1.id = t2.id), usamos operadores lógicos (BETWEEN, >, <). SQL solo retiene las combinaciones donde las cifras "caen" en las casillas correctas.

Si te encuentras atascado intentando hacer un bucle complejo en un paso DATA porque no tienes una clave común: piensa en SQL.

No te encierres en la idea de que una unión requiere una columna idéntica. Siempre que puedas definir una regla lógica (como "estar entre X e Y"), la PROC SQL puede hacer el trabajo de manera mucho más concisa.