Definir o universo antes da consulta
Uma consulta correta pode responder à pergunta errada. Antes de escrever SQL, define o serviço, período, tipo de evento e critério que queres avaliar. No exercício, o universo são seis deployments fictícios, D1 a D6, registados numa janela em UTC. O objetivo inicial é relacionar cada deployment com a respetiva mudança, sem perder eventos por falta de correspondência. O conjunto foi criado para aprendizagem e não é extraído de produção. A execução confirma comportamento das consultas sobre estes dados; não prova completude de um inventário real nem eficácia de um processo bancário.
O que desaparece numa junção
O INNER JOIN devolve apenas deployments com mudança correspondente. Como C6 não existe, o resultado contém cinco deployments e D6 desaparece. Se o auditor chamar a esse resultado «população completa», transforma uma lacuna em exclusão silenciosa. Usa uma junção que preserve o universo definido e identifica separadamente correspondências em falta. A ausência do registo pode resultar de extração incompleta, identificador incorreto ou mudança sem registo; a consulta não escolhe a causa. Pede corroboração e mantém o item no papel de trabalho enquanto investigas. Não concluas imediatamente que alguém alterou produção sem autorização.
Duplicação e unidade de análise
C1 tem duas aprovações. Juntar deployments a aprovações produz sete linhas, apesar de continuarem a existir seis deployments. COUNT(DISTINCT d.id) recupera a contagem de identificadores nesta consulta, mas não corrige automaticamente todas as análises: somar custos ou durações após a junção pode continuar a duplicar valores. Define a unidade de análise e agrega cada relação no nível adequado antes de calcular totais. Conserva o detalhe necessário à decisão. Escolher arbitrariamente a primeira aprovação pode esconder que uma aprovação ocorreu depois da execução ou que o aprovador não tinha autoridade.
Reproduzir e desafiar o resultado
Regista origem, data de extração, filtros, versão da consulta, transformação, contagens de entrada e resultado. Preserva uma cópia autorizada do conjunto utilizado e limita acesso ao que contém. Um revisor deve conseguir repetir o cálculo e compreender a ligação entre critério e conclusão. Testa também casos que desafiam a lógica: identificador sem correspondência, aprovação duplicada, campo nulo e classificação de emergência. Se um teste conhecido produz uma conclusão errada, corrige a consulta e identifica os resultados anteriores afetados. O sucesso num único conjunto não demonstra que todos os formatos futuros serão interpretados corretamente.
Exercício e conclusão limitada
Executa o código desta aula numa base SQLite vazia e descartável. A primeira contagem deve ser seis; a junção interna dá cinco; a junção com aprovações dá sete linhas. Identifica D6 como correspondência em falta e explica por que nenhuma destas contagens representa, sozinha, uma taxa de incumprimento. Escreve uma conclusão com quatro elementos: universo, procedimento, resultado e limite. Exemplo: «Nos seis deployments sintéticos, um não tem mudança correspondente no conjunto fornecido; é necessária corroboração antes de classificar a causa.» Esta formulação comunica a lacuna sem afirmar fraude, incumprimento universal ou validade estatística de uma amostra.
-- Original synthetic audit evidence. Times are integer UTC minutes within one day.
CREATE TABLE deployments(id TEXT PRIMARY KEY, change_id TEXT, digest TEXT NOT NULL, deployed_minute INTEGER NOT NULL, operator TEXT NOT NULL);
CREATE TABLE changes(id TEXT PRIMARY KEY, class TEXT NOT NULL, approved_digest TEXT);
CREATE TABLE approvals(id TEXT PRIMARY KEY, change_id TEXT NOT NULL, approved_minute INTEGER NOT NULL, approver TEXT NOT NULL);
INSERT INTO deployments VALUES('D1','C1','digest-A',600,'ops-a'),('D2','C2','digest-B',610,'ops-b'),('D3','C3','digest-C',620,'ops-c'),('D4','C4','digest-D',630,'ops-d'),('D5','C5','digest-E',640,'ops-e'),('D6','C6','digest-F',650,'ops-f');
INSERT INTO changes VALUES('C1','standard','digest-A'),('C2','standard','digest-old'),('C3','standard','digest-C'),('C4','emergency',NULL),('C5','standard','digest-E');
INSERT INTO approvals VALUES('A1','C1',590,'review-a'),('A2','C1',595,'review-b'),('A3','C2',600,'review-c'),('A4','C3',625,'review-d'),('A5','C5',630,'ops-e');
CREATE TABLE recovery(id TEXT PRIMARY KEY, elapsed INTEGER, rto INTEGER, data_gap INTEGER, rpo INTEGER, key_available INTEGER, partner_validated INTEGER, business_accepted INTEGER);
INSERT INTO recovery VALUES('R1',40,45,3,5,1,1,1),('R2',20,45,1,5,0,0,0),('R3',44,45,7,5,1,1,1),('R4',35,45,3,5,1,0,0),('R5',30,45,NULL,5,1,1,1);
SELECT COUNT(*) FROM deployments;
SELECT COUNT(*) FROM deployments d JOIN changes c ON c.id=d.change_id;
SELECT d.id FROM deployments d LEFT JOIN changes c ON c.id=d.change_id WHERE c.id IS NULL;
SELECT COUNT(*),COUNT(DISTINCT d.id) FROM deployments d LEFT JOIN approvals a ON a.change_id=d.change_id;D6 desaparece no INNER JOIN e C1 duplica linhas na junção com aprovações. O auditor reconcilia identificadores antes de calcular indicadores.
Armadilhas comuns
Usar linhas de uma junção como deployments; apagar exceções com filtros; inferir causa a partir de ausência; usar DISTINCT como correção universal.
Tópicos relacionados: Evidência e amostragem · SQL e dados nulos
A conclusão depende do universo preservado e da transformação demonstrada. Uma consulta não substitui corroboração nem justifica extrapolação sem base.
Referência: Assessing Security and Privacy Controls in Information Systems and Organizations · CISA outline effective August 1, 2024