1
resposta

Resolução - identificar clientes com todos os empréstimos quitados

Boa noite!

SELECT
    NOME,
    EMAIL,
    TO_CHAR(VALOR, 'L999G999G990D00', 'NLS_NUMERIC_CHARACTERS = '',.''') AS VALOR
FROM
    CLIENTES
JOIN
    EMPRESTIMO
ON
    CLIENTES.ID_CLIENTE = EMPRESTIMO.ID_CLIENTE
WHERE NOT EXISTS (
    SELECT
    1
FROM
    PAGAMENTOS
WHERE
    PAGAMENTOS.ID_EMPRESTIMO = EMPRESTIMO.ID_EMPRESTIMO AND STATUS != 'Pago'
);

Saída:

Insira aqui a descrição dessa imagem para ajudar na acessibilidade

1 resposta

Olá, Estudante. Como vai?

Boa noite! A sua solução ficou excelente e o resultado exibido na imagem comprova que a query está funcionando perfeitamente. Você utilizou conceitos avançados muito importantes, como o JOIN para relacionar as tabelas, a formatação de moeda com o TO_CHAR (essencial para apresentar os dados de forma limpa) e a cláusula NOT EXISTS.

A estrutura do NOT EXISTS com uma subconsulta correlacionada é uma das formas mais eficientes de resolver esse tipo de problema, pois o banco de dados interrompe a busca assim que encontra a primeira condição que quebra a regra, economizando processamento.

Para enriquecer ainda mais o seu aprendizado sobre subconsultas e bancos de dados, quero trazer um ponto de atenção técnico sobre a lógica de negócio envolvida nesse cenário:

Atenção ao cenário de Empréstimos sem nenhum pagamento registrado
A sua subconsulta no WHERE NOT EXISTS está buscando registros onde o STATUS != 'Pago'. Essa lógica funciona perfeitamente se todos os empréstimos já possuírem parcelas ou registros na tabela de pagamentos.

Contudo, na rotina de um banco de dados real, se um cliente fizer um empréstimo hoje e nenhuma parcela tiver sido gerada ou paga ainda (ou seja, não há nenhuma linha correspondente na tabela PAGAMENTOS), a sua subconsulta retornará vazia. Como o resultado é vazio, o NOT EXISTS entenderá que "não existem parcelas diferentes de Pago" e trará esse cliente na lista como se ele estivesse com tudo quitado, quando na verdade ele acabou de pegar o dinheiro.

Como deixar a sua Query ainda mais robusta:
Para garantir que o cliente só apareça na lista se ele realmente tiver todas as parcelas pagas e que existam parcelas pagas, podemos ajustar a subconsulta para verificar se existe alguma parcela pendente ou aberta, ou fazer a validação invertida com o EXISTS.

Uma alternativa muito utilizada no mercado para esse tipo de relatório é usar a agregação com HAVING, comparando o total de empréstimos com o total de empréstimos pagos:

SELECT
    C.NOME,
    C.EMAIL,
    TO_CHAR(E.VALOR, 'L999G999G990D00', 'NLS_NUMERIC_CHARACTERS = '',.''') AS VALOR
FROM
    CLIENTES C
JOIN
    EMPRESTIMO E ON C.ID_CLIENTE = E.ID_CLIENTE
WHERE 
    E.ID_EMPRESTIMO IN (
        SELECT ID_EMPRESTIMO 
        FROM PAGAMENTOS 
        GROUP BY ID_EMPRESTIMO 
        HAVING COUNT(CASE WHEN STATUS != 'Pago' THEN 1 END) = 0
    );

Usar apelidos nas tabelas (como C para CLIENTES e E para EMPRESTAO) também ajuda a deixar o seu código mais legível e rápido de digitar no dia a dia.

Parabéns pelo excelente domínio das funções de formatação e pela estrutura lógica da sua query. É muito bom ver você praticando com desafios complexos de subconsultas!

Espero que possa ter lhe ajudado!