¿Para qué sirven EXCLUDE y RENAME?
En el release de noviembre de 2022, Snowflake anunció discretamente una nueva sintaxis SQL muy interesante: EXCLUDE y RENAME, que permite quitar y renombrar columnas específicas al ejecutar una consulta tipo SELECT . Resulta especialmente útil porque, en flujos de trabajo SQL fuera de producción, es muy común lanzar consultas exploratorias del tipo `SELECT ` como:
select *
from table
where id = 5
Esto suele hacerse para investigar un registro o un subconjunto de registros en particular. Pero, ¿qué pasa cuando quieres excluir una columna específica (como una columna de texto extensa) o renombrar alguna? Te ves obligado a escribir todas las columnas que quieres, junto con los renombrados deseados usando la sintaxis tradicional AS:
select
column_1,
column_2,
column_3 as column_3_renamed,
column_4,
column_5,
column_6,
column_7,
column_8,
column_9, -- columns 10 and 11 are intentionally left out
column_12
from table
where id = 5
No es lo ideal cuando buscas respuestas rápidas.
¿Cómo excluir columnas al ejecutar una sentencia SELECT \* en Snowflake?
En lugar de escribir cada columna, una petición frecuente
1 de los usuarios es poder indicar un subconjunto de columnas que se quieren excluir de la tabla. En muchos casos resulta mucho más eficiente, ya que la cantidad de columnas a excluir suele ser bastante menor que las que se quieren incluir. Desde el release 6.37 de Snowflake, ya puedes incluir una cláusula EXCLUDE en consultas SQL tipo SELECT * e indicar una o más columnas que no quieres que se devuelvan:
select
*
exclude(column_10, column_11)
from table
where id = 5
También sirve para excluir una sola columna:
select
*
exclude (column_10)
from table
where id = 5
Los paréntesis son opcionales cuando se excluye una sola columna. El SQL anterior puede reescribirse así:
select
*
exclude column_10
from table
where id = 5
Uso de EXCLUDE de Snowflake con varias tablas
Otra necesidad habitual al excluir columnas surge al unir varias tablas. Imagina una consulta como esta 2:
select
orders.*,
customers.* exclude customer_id,
items.* exclude order_id
from orders
join customers
on orders.customer_id=customers.customer_id
join items
on orders.order_id=items.order_id
En este ejemplo, en el resultado aparecen dos columnas order_id y dos columnas customer_id, ya que están presentes en varias tablas. Se pueden excluir fácilmente modificando el SQL así:
select
orders.*,
customers.* exclude customer_id,
items.* exclude order_id
from orders
join customers
on orders.customer_id=customers.customer_id
join items
on orders.order_id=items.order_id
El equivalente en Snowflake al EXCEPT de BigQuery y Databricks
La sintaxis EXCLUDE de Snowflake es similar a la sintaxis EXCEPT de BigQuery y Databricks:
-- Snowflake
select
*
exclude(column_10, column_11)
from table
-- BigQuery/Databricks
select
*
except(column_10, column_11)
from table
Si conoces DuckDB, Snowflake adopta la misma sintaxis EXCLUDE que ellos usan. Lo más probable es que ambas bases de datos optaran por evitar la palabra clave EXCEPT para esta funcionalidad, dado que ya se usa en operaciones de conjuntos.
¿Conviene usar EXCLUDE en código SQL de producción?
Aunque esta nueva sintaxis es excelente para agilizar flujos ad hoc, no se recomienda para código SQL de producción. Es preferible ser explícito sobre las columnas que estás seleccionando. Escribir todos los nombres de columnas mejora la legibilidad y la auditoría del código. Quien lo lea entenderá de inmediato qué columnas se usan y de qué tabla provienen. Además, los errores resultan más claros: si de pronto se elimina una columna de una tabla, tu código SQL fallará al instante, lo cual es mucho mejor que ver caer una aplicación posterior por una columna que ya no existe.
¿Usar EXCLUDE en Snowflake genera un plan de consulta o un rendimiento distinto?
No. Usar la palabra clave EXCLUDE para quitar algunas columnas no produce un plan de consulta ni un rendimiento distinto frente a escribir todas las columnas de forma explícita. Puedes comprobarlo ejecutando ambos tipos de consulta sobre un dataset en tu cuenta de Snowflake y revisando el query profile de cada una.
¿Cómo renombrar columnas al ejecutar una sentencia SELECT \* en Snowflake?
Antes de la nueva funcionalidad RENAME, había que escribir el nombre de cada columna en cuanto se quería renombrar al menos una al ejecutar un SELECT *. Ahora puedes seleccionar todas las columnas y renombrar solo un subconjunto:
select
*
rename (column_3 as column_3_renamed, column_5 as column_5_renamed)
from table
where id = 5
Mucho mejor que tener que listar cada campo solo para renombrar uno o dos:
-- old method 👎
select
column_1,
column_2,
column_3 as column_3_renamed,
column_4,
column_5 as column_5_renamed,
column_6,
...
column_12
from table
where id = 5
Al igual que con EXCLUDE, también puede aplicarse a una sola columna, con paréntesis opcionales:
select
*
rename (column_3 as column_3_renamed)
from table
where id = 5
Combinar EXCLUDE y RENAME
EXCLUDE y RENAME se pueden combinar fácilmente, como muestra el siguiente ejemplo:
select
*
exclude(column_10, column_11)
rename column_3 as column_3_renamed
from table
where id = 5
Mucho mejor que el código del inicio del post:
select
column_1,
column_2,
column_3 as column_3_renamed,
column_4,
column_5,
column_6,
column_7,
column_8,
column_9, -- columns 10 and 11 are intentionally left out
column_12
from table
where id = 5
Notas
Para que te hagas una idea de la demanda, esta pregunta de Stack Overflow, publicada hace casi 14 años, acumula 1.3 millones de vistas y más de 1000 upvotes.
¡Un saludo a Nate Sooter por inspirar este ejemplo con su tweet reciente!
Ian Whitestone·Co-founder & CEO de SELECT
Ian es Co-founder y CEO de SELECT, una plataforma SaaS de gestión y optimización de costos para Snowflake. Antes de fundar SELECT, Ian pasó 6 años liderando equipos full stack de data science e ingeniería en Shopify y Capital One. En Shopify, lideró los esfuerzos para optimizar el data warehouse y mejorar la visibilidad de los costos.