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:

01_Fig_01.gif
Importante: O campo TIPO, da tabela TELEFONES, indica o tipo de telefone que o cliente possui, de acordo com a seguinte convenção:
  • 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:

01_Fig_02.gif

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