Fedsql

SAS y SQL: Cómo replicar OVER PARTITION BY en SAS

Simon 10 vistas

Para los analistas de datos que provienen del mundo SQL estándar (Oracle, SQL Server, PostgreSQL), una de las primeras frustraciones en SAS© es la aparente falta de soporte para las funciones de ventana (Window Functions).

Sintaxis comunes como ROW_NUMBER() OVER (PARTITION BY id ORDER BY date) o SUM(val) OVER (PARTITION BY group) provocan errores de sintaxis inmediatos en la PROC SQL de SAS©.

Este artículo explica por qué existe esta limitación y, sobre todo, cómo sortearla eficazmente utilizando la potencia nativa del lenguaje SAS©.

La constatación: PROC SQL y el estándar ANSI

El procedimiento estándar PROC SQL de SAS© se basa en una versión antigua del estándar ANSI (principalmente ANSI 92). Las funciones de ventana (introducidas más tarde en el estándar SQL:2003) no son compatibles con el motor SQL nativo de SAS© Base.

Es inútil buscar una opción oculta: PROC SQL no entenderá la cláusula OVER. Sin embargo, SAS© ofrece varias alternativas a menudo más eficientes para obtener el mismo resultado.

Alternativa 1: El enfoque nativo de SAS© (DATA Step)

Este es el método más "SAS©". En lugar de pensar en términos de consultas de conjuntos, se utiliza el procesamiento secuencial del DATA Step combinado con grupos (BY groups). Es el equivalente directo de PARTITION BY.

La lógica de correspondencia

  • SQL: PARTITION BY variable

  • SAS©: BY variable (requiere una ordenación previa)

  • SQL: ORDER BY date

  • SAS©: PROC SORT por fecha

Ejemplo: Replicar un ROW_NUMBER()

Imaginemos que queremos numerar filas para cada cliente, ordenadas por fecha.

En SQL estándar:

1SELECT customer_id,
2ROW_NUMBER() OVER (PARTITION BY customer_id ORDER BY trans_date) as row_num
3FROM transactions;
4 

En SAS© (DATA Step): Este método utiliza las variables automáticas FIRST. para detectar el cambio de grupo.

1/* 1. Le tri est obligatoire pour utiliser BY */
2PROC SORT DATA=transactions;
3 BY customer_id trans_date;
4RUN;
5 
6/* 2. Le Data Step */
7DATA want;
8 SET transactions;
9 BY customer_id;
10
11 /* Si c'est la première ligne du client, on remet le compteur à 1 */
12 IF first.customer_id THEN row_num = 1;
13 /* Sinon, on incrémente */
14 ELSE row_num + 1;
15RUN;

Ejemplo: Replicar un SUM() Acumulativo

En SQL estándar: SUM(amount) OVER (PARTITION BY customer_id ORDER BY date)

En SAS© (DATA Step):

1DATA want;
2 SET transactions;
3 BY customer_id;
4
5 /* RETAIN garde la valeur de la ligne précédente */
6 retain running_total;
7
8 IF first.customer_id THEN running_total = amount;
9 ELSE running_total = running_total + amount;
10RUN;

Alternativa 2: El SQL Pass-Through (Delegación)

Si sus datos ya residen en una base de datos potente (Oracle, SQL Server, Teradata) y utiliza SAS©/ACCESS, a menudo es más eficiente dejar que la base de datos haga el trabajo.

Esta técnica, llamada Explicit Pass-Through, envía su código SQL nativo directamente al servidor de la base de datos. SAS© no lo interpreta, solo recibe el resultado.

1PROC SQL;
2 connect to oracle (user=... pass=... path=...);
3
4 create TABLE want as
5 select * from connection to oracle
6 (
7 /* Ici, vous pouvez utiliser toute la syntaxe Oracle,
8 y compris les fonctions de fenêtrage */
9 SELECT
10 customer_id,
11 trans_date,
12 RANK() OVER (PARTITION BY customer_id ORDER BY trans_date DESC) as rang
13 FROM
14 schema.transactions
15 );
16
17 disconnect from oracle;
18QUIT;
Ventaja: Utiliza la sintaxis SQL que ya conoce y aprovecha la potencia del servidor de la base de datos.

Alternativa 3: Los Procedimientos Específicos

Para algunas funciones de ventana comunes como RANK o los deciles (NTILE), SAS© dispone de procedimientos dedicados optimizados que evitan escribir código complejo.

Para reemplazar RANK() OVER (PARTITION BY ...):

1PROC RANK DATA=transactions out=want descending;
2 BY customer_id; /* Équivalent du PARTITION BY */
3 var amount; /* La variable sur laquelle on classe */
4 ranks my_rank; /* Le nom de la nouvelle colonne */
5RUN;

¿Qué pasa con PROC FEDSQL?

SAS© introdujo un procedimiento más moderno llamado PROC FEDSQL, que busca una conformidad ANSI SQL más estricta (SQL:1999 y posteriores). Aunque FedSQL es mucho más avanzado que PROC SQL, el soporte completo de las funciones de ventana depende en gran medida del entorno (SAS© 9 vs SAS© Viya/CAS) y a veces sigue siendo limitado en comparación con las bases de datos nativas. Se recomienda consultar la documentación específica de su versión de SAS©, pero para las necesidades de ventana clásicas, el Data Step sigue siendo a menudo la mejor opción en términos de rendimiento local.

Necesidad SQLSolución SAS© Recomendada
Datos locales (conjuntos de datos SAS©)Utilice el DATA Step con BY, FIRST., LAST. y RETAIN. Es rápido y flexible.
Datos en una DB (Oracle, etc.)Utilice el SQL Pass-Through (CONNECT TO) para ejecutar el SQL nativo.
Cálculo de Rangos / PercentilesUtilice PROC RANK o PROC UNIVARIATE.
Consultas simplesQuédese con PROC SQL estándar (sin funciones de ventana).