Este repositório contém um ambiente completo de Engenharia de Dados focado em limpeza, padronização e deduplicação de dados (Fuzzy Matching) utilizando PostgreSQL.
O projeto foi desenhado para acompanhar a série de posts #sqlpilulas no LinkedIn.
Simular um cenário real onde recebemos dados "sujos" de cadastro de empresas (CNPJs) e precisamos saneá-los utilizando apenas recursos nativos do banco de dados, sem ferramentas externas de ETL.
Baseado em conceitos do livro Fuzzy Data Matching with SQL e adaptado para cenários brasileiros (CNPJ, CPF, Acentuação).
- Banco de Dados: PostgreSQL 16
- Infraestrutura: Docker & Docker Compose
- Gerador de Dados: Python 3 (Native libraries)
- Docker e Docker Compose instalados
- Python 3.11+ (para gerar o CSV)
git clone [https://github.com/SEU_USUARIO/sql-fuzzy-lab.git](https://github.com/SEU_USUARIO/sql-fuzzy-lab.git)
cd sql-fuzzy-labO gerador de caos usa como base os dados abertos da Receita Federal. Faça o download:
- Acesse: https://arquivos.receitafederal.gov.br/dados/cnpj/dados_abertos_cnpj/
- Baixe o arquivo
Empresa.zip(dados de empresas) - Descompacte e rename para
data/empresas_limpas.csv
# Exemplo (ajuste conforme o arquivo baixado)
unzip Empresa.zip -d temp/
mv temp/Empresa.csv data/empresas_limpas.csv
rm -rf temp/Nota: Este CSV contém +10M de registros reais do Brasil. O script Python usará este como base para gerar variações "sujas".
Use o script em python/gerador_caos.py para gerar dados de teste (baseado no CSV limpo):
# Gerar tudo (~4.7M linhas, pode levar alguns minutos)
python3 python/gerador_caos.py --seed 42
# Teste rápido com limite (1.000 linhas)
python3 python/gerador_caos.py --seed 42 --limit 1000
# Validar um CSV já gerado
python3 python/gerador_caos.py --validate-only --output data/empresas_sujas.csvSaída esperada: data/empresas_sujas.csv (delimitador ;, com header)
docker compose up -dO arquivo docker-compose.yml automaticamente:
- Monta
./sql/init.sqlna inicialização do BD - Carrega
./data/empresas_sujas.csvviaCOPYcom tratamento de encoding
Importante: Gere
data/empresas_sujas.csvantes dedocker compose up, pois oinit.sqlexecuta na inicialização.
Host: localhost
Port: 5432
User: admin
Password: sqlpilulas_pass
Database: cnpj_labTeste a conexão:
docker compose exec -T database psql -U admin -d cnpj_lab -c "SELECT count(*) FROM stg_empresas_import;"- Infraestrutura como Código (Docker)
- Gerador de Dados Sujos (Python + CSV)
- Carregamento em Staging (PostgreSQL COPY)
- Padronização de Strings (RegEx, TRANSLATE, TRIM)
- Limpeza de Máscaras e RegEx
- Algoritmos Fonéticos (Soundex)
- Distância de Edição (Levenshtein)
- Deduplicação de Registros
As queries demonstram técnicas práticas de limpeza e normalização de dados. Todas estão em sql/book_queries/:
Arquivo: query_post1.sql
Técnica para remover números indesejados no final de strings usando REGEXP_REPLACE:
REGEXP_REPLACE(nome_fantasia, '[0-9]+$', '')Caso de uso: Nomes de empresas com CPF/CNPJ concatenados ao final.
Arquivo: query_post2.sql
Mais eficiente que múltiplos REPLACE para remover caracteres especiais:
TRANSLATE(nome_fantasia, '.-/', '') -- Remove ponto, traço, barraCaso de uso: CEP com ou sem máscara, nomes com pontuação variada.
Arquivo: query_post3.sql
Elimina termos como LTDA, ME, S.A. que atrapalham a comparação:
REGEXP_REPLACE(nome_fantasia, '\s+(LTDA|ME|EPP|EIRELI|S\.A\.|S/A|LIMITADA)\.?$', '', 'gi')Caso de uso: Encontrar o "núcleo" do nome da empresa ignorando sufixos legais.
Arquivo: query_post4.sql
Arquivo: query_post5.sql
Se precisar recarregar sem recriar o container:
cat <<'SQL' | docker compose exec -T database psql -U admin -d cnpj_lab
TRUNCATE stg_empresas_import;
COPY stg_empresas_import (
cnpj_basico, cnpj_ordem, cnpj_dv, identificador, nome_fantasia,
situacao_cadastral, data_situacao_cadastral, motivo_situacao_cadastral,
nome_da_cidade_no_exterior, pais, data_de_inicio_atividade,
cnae_fiscal_principal, cnae_fiscal_secundaria, tipo_de_logradouro,
logradouro, numero, complemento, bairro, cep, uf, municipio
) FROM PROGRAM 'tr "\000" " " < /docker-entrypoint-initdb.d/empresas_sujas.csv'
WITH (FORMAT csv, HEADER true, DELIMITER ';', QUOTE '"', ENCODING 'UTF8');
SQLNota: O
trremove bytes nulos que causariam erro de encoding UTF-8.
docker compose down -v
docker compose up -d- A tabela
stg_empresas_importusa colunasTEXTpara aceitar dados "sujos" - Se mudar o caminho do CSV ou delimitador, ajuste
sql/init.sqledocker-compose.yml - O script Python inclui várias transformações ("caos"): typos, formatações brasileiras, CPF colado, etc.
Desenvolvido para aprender Data Quality e Fuzzy Matching com SQL puro. 🚀