Por que precisamos do EXCLUDE e do RENAME?
No release de novembro de 2022, o Snowflake anunciou discretamente uma nova sintaxe SQL bem interessante, EXCLUDE e RENAME, que permite remover e renomear colunas específicas em consultas do tipo SELECT . Isso é especialmente útil, já que é muito comum, em workflows SQL fora de produção, rodar consultas exploratórias no estilo `SELECT `, como:
select *
from table
where id = 5
Normalmente fazemos isso para investigar um registro específico ou um subconjunto de registros. Mas e quando você quer excluir uma coluna específica (como uma coluna de texto muito grande) ou renomear alguma delas? Aí não tem jeito: é preciso digitar todas as colunas desejadas, junto com as renomeações usando a sintaxe 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
Nada prático quando você precisa de respostas rápidas.
Como excluir colunas ao executar um SELECT \* no Snowflake?
Em vez de digitar coluna por coluna, um pedido recorrente
1 dos usuários é poder especificar um subconjunto de colunas a serem excluídas da tabela. Em muitos casos, isso é bem mais eficiente, já que o número de colunas a excluir costuma ser bem menor do que o número a incluir. A partir do release 6.37 do Snowflake, agora dá para incluir uma cláusula EXCLUDE em consultas SQL do tipo SELECT *, indicando uma ou mais colunas que você não quer que sejam retornadas:
select
*
exclude(column_10, column_11)
from table
where id = 5
Também é possível usar para excluir uma única coluna:
select
*
exclude (column_10)
from table
where id = 5
Os parênteses são opcionais quando se exclui uma única coluna. O SQL acima pode ser reescrito assim:
select
*
exclude column_10
from table
where id = 5
Usando o EXCLUDE do Snowflake com várias tabelas
Outra situação em que excluir colunas é útil é ao fazer join entre várias tabelas. Imagine uma 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
Neste exemplo, temos duas colunas order_id e duas colunas customer_id no resultado, porque elas aparecem em mais de uma tabela. Dá para excluí-las facilmente ajustando o SQL para:
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
O equivalente do Snowflake ao EXCEPT do BigQuery e do Databricks
A sintaxe EXCLUDE do Snowflake é parecida com o EXCEPT do BigQuery e do Databricks:
-- Snowflake
select
*
exclude(column_10, column_11)
from table
-- BigQuery/Databricks
select
*
except(column_10, column_11)
from table
Para quem já conhece o DuckDB, o Snowflake adotou a mesma sintaxe EXCLUDE usada por ele. Provavelmente os dois bancos optaram por não usar a palavra-chave EXCEPT para essa funcionalidade porque ela já é usada em operações de conjunto.
Vale a pena usar EXCLUDE em código SQL de produção?
Embora a nova sintaxe seja ótima para agilizar workflows ad hoc, ela não é recomendada para código SQL de produção. O ideal é ser explícito sobre exatamente quais colunas você está selecionando. Listar todos os nomes de coluna melhora a legibilidade e a auditabilidade. Quem lê seu SQL entende na hora quais colunas você está usando de cada tabela. Isso também ajuda a gerar erros mais claros: se uma coluna for removida da tabela, seu SQL vai falhar de imediato — bem melhor do que uma aplicação downstream quebrar de surpresa por causa de uma coluna ausente.
Usar EXCLUDE no Snowflake gera um query plan ou desempenho diferente?
Não. Usar a palavra-chave EXCLUDE para remover algumas colunas não muda o query plan nem o desempenho da consulta em comparação a listar todas as colunas explicitamente. Você mesmo pode validar esse comportamento rodando os dois tipos de consulta em um dataset da sua conta Snowflake e inspecionando o query profile de cada uma.
Como renomear colunas ao executar um SELECT \* no Snowflake?
Antes da nova funcionalidade RENAME, bastava precisar renomear uma única coluna em um SELECT * para ser obrigado a listar todas as outras. Agora dá para selecionar todas as colunas e renomear apenas um subconjunto:
select
*
rename (column_3 as column_3_renamed, column_5 as column_5_renamed)
from table
where id = 5
Muito melhor do que ter que listar todos os campos só para renomear um ou dois:
-- 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
Assim como no EXCLUDE, também funciona para uma única coluna, com parênteses opcionais:
select
*
rename (column_3 as column_3_renamed)
from table
where id = 5
Combinando EXCLUDE e RENAME
Dá para combinar EXCLUDE e RENAME tranquilamente, como no exemplo abaixo:
select
*
exclude(column_10, column_11)
rename column_3 as column_3_renamed
from table
where id = 5
Bem melhor do que o código mostrado no começo do 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 você ter uma ideia da demanda, esta pergunta no Stack Overflow, feita há quase 14 anos, tem 1,3 milhão de visualizações e mais de 1.000 upvotes
Valeu, Nate Sooter, por inspirar este exemplo com seu tweet recente!
Ian Whitestone·Cofundador e CEO da SELECT
Ian é cofundador e CEO da SELECT, uma plataforma SaaS de gestão e otimização de custos do Snowflake. Antes de fundar a SELECT, Ian passou 6 anos liderando times full stack de data science e engenharia na Shopify e na Capital One. Na Shopify, Ian liderou o trabalho de otimizar o data warehouse e ampliar a observabilidade de custos.