Prezado internauta, neste primeiro artigo lanço um interessante desafio envolvendo consulta SQL. Este exercício foi validado no SGBD MySQL Versão 4.
Observe atentamente a descrição do problema: temos uma tabela de cadastro de clientes, e outra que armazena seus telefones. Observe a estrutura abaixo:
- RES para residencial;
- CEL para celular;
- FAX para fax.
De acordo com o diagrama acima, um cliente pode ter vários telefones.
Para facilitar, aqui você pode baixar um script SQL que:
- cria as tabelas, implementando o relacionamento;
- cadastra alguns registros.
O desafio é: faça uma consulta SQL, ordenada pelo campo nome, que retorne: o nome dos clientes, bem como seus telefones (residencial, fax e celular) nesta ordem, uma linha por cliente. Mesmo que o cliente não possua telefone, ele deve sair no resultado da consulta.
Para facilitar o entendimento do desafio, considerando os dados fornecidos no script SQL, a consulta retorna o seguinte resultado:
a seguir darei a solução e publicarei o nome das pessoas que conseguirem resolver essa consulta corretamente.
Solução
Apresento a resposta do desafio. Trata-se de um problema genérico de “inversão de papeis”, ou seja, existem situações em que precisamos mostrar o conteúdo de diversas linhas (registros) em apenas uma. Observe a solução abaixo:
SELECT C.NOME,
TRES.FONE RESIDENCIAL,
TFAX.FONE FAX,
TCEL.FONE CELULAR
FROM CLIENTES C LEFT OUTER JOIN TELEFONES TRES ON
(C.CODIGO=TRES.CODIGO AND TRES.TIPO='RES')
LEFT OUTER JOIN TELEFONES TFAX ON
(C.CODIGO=TFAX.CODIGO AND TFAX.TIPO='FAX')
LEFT OUTER JOIN TELEFONES TCEL ON
(C.CODIGO=TCEL.CODIGO AND TCEL.TIPO='CEL')
ORDER BY C.NOME
Neste caso, utilizamos o LEFT OUTER JOIN para poder mostrar todos os registros da tabela de CLIENTES, mesmo não havendo ocorrência na tabela de TELEFONES – neste caso, o valor do campo FONE é nulo. Essa operação é necessária para cada tipo de telefone existente.
Vale lembrar que esta consulta foi validada no SGBD MySQL versão 4.
Para minha surpresa, recebi muitos emails, precisamente 45, até o dia 13/05 às 14:30h, quando finalizei este artigo.
Os leitores mandaram soluções testadas em diversos SGBDs – MySQL, Oracle, Firebird, entre outros. Outros ainda mandaram solução usando stored procedure. Olhei a estrutura de todas as consultas mas não tive como “rodar” as soluções de outros SGBDs. Em alguns casos rodei a solução no próprio MySQL.
Outro detalhe interessante é que alguns leitores, bastante atentos, observaram uma falha conceitual no script SQL – criação da tabela de TELEFONES. Observe:
... CREATE TABLE TELEFONES
(CODIGO INTEGER,
TIPO CHAR(3) NOT NULL ,...
A definição do campo código deveria ter a cláusula NOT NULL, ficando dessa forma:
... CREATE TABLE TELEFONES
(CODIGO INTEGER NOT NULL,
TIPO CHAR(3) NOT NULL, ...
Abaixo os nomes das pessoas que acertaram, pela ordem de chegada dos e-mails. Parabéns a todos!!
- Everton Garcia
- Júlio Souza
- Leonardo Jordão
- Lucimar Santos
- Claudio Souza
- Rodrigo Fernandes
- Anderson Ouverney
- Wagner Crivelini
- Robson Branco
- Marcelo Colla
- Ederson Selvati
- Cristiano Rebonatto
- Fabricio Baptista
- Cristiano Scofield
- Giovani Decusati
- Demetrius Nogueira
- Marcin Babinski
- Roberto Enomoto
- Carlos Braga
- Romildo Cruz
- Bruno Andrade
- Jony Ridel
- João Almeida
- Daniel Garcia
- Daniel Gonçalves
- Claudio Silva
- Vanius Girodo
- Luthiano Vasconcelos
- Everton Bomfim
- Marcelo Nashiro
- Gustavo Ribeiro
- Ivo Christian
- César Alencar