Considere o script SQL a seguir. CREATE TABLE Processo ( id_processo INT PRIMARY KEY, numero VARCHAR(20) NOT NULL); CREATE TABLE mov ( id_mov SERIAL PRIMARY KEY, id_processo INT NOT NULL, data_mov DATE NOT NULL, FOREIGN KEY (id_processo) REFERENCES processo(id_processo) ); INSERT INTO Processo (id_processo, numero) VALUES (1, 'P1'), (2, 'P2'), (3, 'P3'), (4, 'P4'); INSERT INTO Mov (id_processo, data_mov) VALUES (1, '2023-05-10'), (1, '2023-06-01'), (2, '2023-08-15'), (3, '2024-02-20'); Para listar o número do processo e a última data de movimentação, exibindo somente os processos que possuem movimentação, deve-se utilizar a query:
ASELECT p.numero, m.data_mov FROM Processo p LEFT JOIN Mov m ON p.id_processo = m.id_processo;
BSELECT p.numero, m.data_mov FROM Processo p RIGHT JOIN Mov m ON p.id_processo = m.id_processo WHERE m.data_mov IS NOT NULL;
CSELECT p.numero, m.data_mov FROM Processo p INNER JOIN Mov m ON p.id_processo = m.id_processo WHERE m.data_mov = (SELECT MAX(m2.data_mov) FROM Mov m2 WHERE m2.id_processo = p.id_processo);
DSELECT p.numero, m.data_mov FROM Processo p FULL JOIN Mov m ON p.id_processo = m.id_processo;
ESELECT p.numero, m.data_mov FROM Processo p CROSS JOIN Mov m WHERE m.id_processo = p.id_processo and m.data_mov IS NOT NULL;
Revelar gabarito e comentário▾
GabaritoC — SELECT p.numero, m.data_mov
FROM Processo p
INNER JOIN Mov m ON p.id_processo = m.id_processo
WHERE m.data_mov = (SELECT MAX(m2.data_mov) FROM Mov
m2 WHERE m2.id_processo = p.id_processo);
Comentário gerado por IA. É um apoio ao estudo, ancorado em fontes, mas pode conter imprecisões — confira sempre na fonte oficial (lei, súmula, edital e gabarito da banca). Encontrou um erro? Use “Reportar”.
Consultas SQL: junções e agregação para obter a última movimentação
Gabarito: letra C. A consulta correta usa INNER JOIN para restringir aos processos com movimentação e uma subconsulta correlacionada com MAX() para selecionar, para cada processo, apenas a linha de movimentação com a data mais recente. As demais alternativas falham por não filtrar a última data (A, B, D) ou por usar CROSS JOIN de forma incorreta (E).
O problema pede duas coisas simultâneas: (1) listar apenas processos que possuem movimentação e (2) mostrar, para cada um, a última data de movimentação. O primeiro requisito é resolvido com qualquer junção que elimine os processos sem correspondência em Mov — a INNER JOIN é a mais direta. O segundo requisito é o ponto central: não basta juntar as tabelas, é preciso selecionar, entre as várias movimentações de um mesmo processo, apenas aquela com a data máxima.
A subconsulta correlacionada (SELECT MAX(m2.data_mov) FROM Mov m2 WHERE m2.id_processo = p.id_processo) calcula, para cada linha de Processo (aliás p), a maior data de movimentação daquele processo. A condição m.data_mov = ... na cláusula WHERE do INNER JOIN garante que apenas a linha de Mov com essa data máxima seja retornada. Como a subconsulta é correlacionada (referencia p.id_processo de fora), ela é reavaliada para cada processo — é exatamente isso que a torna correta.
Vamos verificar com os dados do enunciado. A tabela Mov tem:
Processo 1: movimentações em 2023-05-10 e 2023-06-01 → última: 2023-06-01
Processo 2: movimentação em 2023-08-15 → última: 2023-08-15
Processo 3: movimentação em 2024-02-20 → última: 2024-02-20
Processo 4: nenhuma movimentação → não deve aparecer
A consulta da alternativa C retorna exatamente: (P1, 2023-06-01), (P2, 2023-08-15), (P3, 2024-02-20). O processo 4 é excluído pelo INNER JOIN.
A pegadinha central desta questão é confundir "juntar as tabelas" com "selecionar a última data". As alternativas A, B e D apenas fazem a junção, sem filtrar a data máxima — elas retornariam todas as movimentações de cada processo (duplicando o processo 1, por exemplo). A alternativa E tenta filtrar com CROSS JOIN, mas sem a subconsulta MAX, também retornaria todas as movimentações.
NÃO CAIA NESSA!
A banca explora a confusão entre fazer a junção e selecionar a última data. Alternativas que apenas juntam as tabelas (A, B, D) parecem corretas à primeira vista, mas retornam todas as movimentações, não apenas a última. A alternativa E tenta compensar com CROSS JOIN, mas sem a subconsulta MAX continua errada. O candidato que não percebe a necessidade de filtrar a data máxima cai nas alternativas A ou B.
1INNER JOIN (só processos com mov.)
2Subconsulta MAX por processo
3Filtra data = MAX (última)
LEVEL · soulevel.com.br
Alternativa A — ❌ Incorreta
O LEFT JOIN preserva todos os registros da tabela Processo (à esquerda), incluindo o processo 4 que não tem movimentação. Além disso, não há filtro para selecionar a última data — a consulta retornaria todas as movimentações de cada processo, duplicando o processo 1 (que tem duas movimentações). O requisito "somente os processos que possuem movimentação" é violado (o processo 4 apareceria com NULL em data_mov), e o requisito "última data" não é atendido.
Alternativa B — ❌ Incorreta
O RIGHT JOIN preserva todos os registros de Mov (à direita), o que já exclui o processo 4 (sem movimentação). O filtro WHERE m.data_mov IS NOT NULL é redundante, pois data_mov é NOT NULL na tabela. Porém, a consulta retorna todas as movimentações de cada processo, sem selecionar a última data — o processo 1 apareceria duas vezes (2023-05-10 e 2023-06-01). Falta a subconsulta com MAX().
Alternativa C — ✅ Correta ⟵ GABARITO
O INNER JOIN restringe aos processos com movimentação (exclui o processo 4). A subconsulta correlacionada (SELECT MAX(m2.data_mov) FROM Mov m2 WHERE m2.id_processo = p.id_processo) calcula a última data de movimentação de cada processo, e a condição m.data_mov = ... no WHERE seleciona apenas a linha com essa data. O resultado é exatamente o pedido: número do processo e última data de movimentação, somente para processos com movimentação.
Alternativa D — ❌ Incorreta
O FULL JOIN preserva todos os registros de ambas as tabelas, incluindo o processo 4 (sem movimentação, com NULL em data_mov). Não há filtro para excluir processos sem movimentação nem para selecionar a última data. A consulta retornaria todas as movimentações de cada processo, duplicando o processo 1, e incluiria o processo 4 com NULL.
Alternativa E — ❌ Incorreta
O CROSS JOIN combina cada linha de Processo com cada linha de Mov, gerando um produto cartesiano. O filtro WHERE m.id_processo = p.id_processo na prática transforma o CROSS JOIN em um INNER JOIN (equivalente à alternativa C sem a subconsulta MAX). Porém, sem a subconsulta MAX, a consulta retorna todas as movimentações de cada processo, duplicando o processo 1. O filtro m.data_mov IS NOT NULL é redundante, pois a coluna é NOT NULL.