[firebase-br] SQL/Consulta complexa - Firebird 2.1

Eduardo Belo beloelogica em gmail.com
Qua Mar 10 16:29:20 -03 2010


Puxa vida Sandro, funcionou perfeitamente.

Muito, muito obrigado pela ajuda. Fico te devendo essa.

Grande abraço!

Em 10 de março de 2010 07:10, Sandro Souza <escovadordebits em gmail.com> escreveu:
> Bom dia/tarde Eduardo.
>
> Grande Eduardo, infelizmente você não conseguirá o resultado que você deseja
> apenas com um simples SELECT.
>
> Por favor, teste a seguinte stored procedure:
>
> SET TERM ^ ;
>
> CREATE OR ALTER PROCEDURE LISTA_INSTRUTORES RETURNS (
>   ID_INSTRUTOR INTEGER,
>   INSTRUTOR VARCHAR(80),
>   EMAIL VARCHAR(80),
>   TELEFONE VARCHAR(14)
> )AS
> DECLARE VARIABLE COUNT_EMAILS INTEGER;
> DECLARE VARIABLE COUNT_TELEFONES INTEGER;
> DECLARE VARIABLE COUNT_MAIOR INTEGER;
> DECLARE VARIABLE INDICE INTEGER;
> BEGIN
>   -- Laço de leitura dos instrutores.
>   FOR SELECT ID_INSTRUTOR, INSTRUTOR FROM INSTRUTORES ORDER BY 2 INTO
> :ID_INSTRUTOR, :INSTRUTOR DO
>   BEGIN
>     -- Obtém a quantidade de emails do instrutor atual.
>     SELECT COUNT(*) FROM EMAILS WHERE ID_INSTRUTOR = :ID_INSTRUTOR INTO
> COUNT_EMAILS;
>     -- Obtém a quantidade de telefones do instrutor atual.
>     SELECT COUNT(*) FROM TELEFONES WHERE ID_INSTRUTOR = :ID_INSTRUTOR INTO
> COUNT_TELEFONES;
>     -- Inicializa os parâmetros de email e telefone a serem retornados.
>     EMAIL = NULL;
>     TELEFONE = NULL;
>     -- O instrutor atual não tem email e nem mesmo um telefone?
>     IF ((COUNT_EMAILS = 0)AND(COUNT_TELEFONES = 0)) THEN
>       -- Retorna um registro/linha contendo apenas o código e o nome do
> instrutor atual.
>       SUSPEND;
>     ELSE
>     BEGIN
>       -- Tem mais emails que telefones?
>       IF (COUNT_EMAILS > COUNT_TELEFONES) THEN
>         -- A maior quantidade é a de emails.
>         COUNT_MAIOR = COUNT_EMAILS;
>       ELSE
>         -- A maior quantidade é a de telefones.
>         COUNT_MAIOR = COUNT_TELEFONES;
>       -- Inicializa o índice dos registros de email e telefone.
>       INDICE = 1;
>       -- Laço de leitura dos emails e telefones.
>       WHILE (INDICE <= COUNT_MAIOR) DO
>       BEGIN
>         -- Todos os emails do instrutor atual foram lidos?
>         IF (INDICE > COUNT_EMAILS) THEN
>           -- Sem mais emails.
>           EMAIL = NULL;
>         ELSE
>           -- Obtém o email da vez.
>           SELECT FIRST 1 SKIP (:INDICE - 1) EMAIL FROM EMAILS WHERE
> ID_INSTRUTOR = :ID_INSTRUTOR INTO :EMAIL;
>         -- Todos os telefones do instrutor atual foram lidos?
>         IF (INDICE > COUNT_TELEFONES) THEN
>           -- Sem mais telefones.
>           TELEFONE = NULL;
>         ELSE
>           -- Obtém o telefone da vez.
>           SELECT FIRST 1 SKIP (:INDICE - 1) TELEFONE FROM TELEFONES WHERE
> ID_INSTRUTOR = :ID_INSTRUTOR INTO :TELEFONE;
>         -- Retorna mais um registro/linha.
>         SUSPEND;
>         -- Atualiza o índice.
>         INDICE = INDICE + 1;
>       END -- WHILE
>     END -- ELSE
>   END -- FOR
> END^
>
> SET TERM ; ^
>
> Agora é só testar: SELECT * FROM LISTA_INSTRUTORES
>
> Espero ter ajudado mais que atrapalhado. :D
>
> Em 9 de março de 2010 12:17, Eduardo Belo <beloelogica em gmail.com> escreveu:
>>
>> Amigos,
>>
>> Tenho as seguintes tabelas:
>>
>> TABLE INSTRUTORES
>>  ID_INSTRUTOR  INTEGER NOT NULL,
>>  INSTRUTOR     VARCHAR(80)
>>
>> TABLE EMAILS
>>  ID_EMAIL      INTEGER NOT NULL,
>>  ID_INSTRUTOR  INTEGER NOT NULL,
>>  EMAIL         VARCHAR(80)
>>
>> TABLE TELEFONES
>>  ID_TELEFONE   INTEGER NOT NULL,
>>  ID_INSTRUTOR  INTEGER NOT NULL,
>>  TELEFONE      VARCHAR(14)
>>
>> CHAVE RELACIONAMENTO = ID_INSTRUTOR
>>
>> ****************************************************
>>
>> Efetuando o select abaixo:
>>
>> SELECT
>>    INSTRUTORES.ID_INSTRUTOR,
>>    INSTRUTORES.INSTRUTOR,
>>    EMAILS.EMAIL,
>>    TELEFONES.TELEFONE
>> FROM TELEFONES
>>   INNER JOIN INSTRUTORES ON (TELEFONES.ID_INSTRUTOR =
>> INSTRUTORES.ID_INSTRUTOR)
>>   INNER JOIN EMAILS ON (INSTRUTORES.ID_INSTRUTOR = EMAILS.ID_INSTRUTOR)
>>
>> Retorno consulta:
>>
>> INSTRUTOR       EMAIL                   TELEFONE
>> --------------------------------------------------
>> MARIA           maria em hotmail.com       8605-9395
>> JOSE            jose em yahoo.com.br       3445-6181
>> JOSE            jose@@hotmail.com       9998-8294
>> JOAO            joao em gmail.com          9133-3824
>> JOAO            joao em gmail.com          3181-8037
>> JOAO            joao em gmail.com          3426-9322
>> JOAO            joao em yahoo.com.br       9133-3824
>> JOAO            joao em yahoo.com.br       3181-8037
>> JOAO            joao em yahoo.com.br       3426-9322
>>
>>
>> Observem que no caso de JOAO ele tem 2 email e 3 telefones e
>> retorna duplicado nos telefones. Eu preciso que nesse caso ele
>> retorne 2 emails e 3 telefones:
>>
>> JOAO            joao em gmail.com          9133-3824
>> JOAO            joao em yahoo.com.br       3181-8037
>> JOAO                                    3426-9322
>>
>> Tem como fazer um SELECT para retornar assim ?
>>
>> Ou existe algum erro na minha modelagem ?
>>
>> Eu preciso de tabelas idependentes de e-mail e teofne uma vez
>> que o instrutor pode ter vários telefones e emails.
>>
>> Qual a solução para este caso?
>>
>> Agradeço a todos que ajudarem.
>>
>> ______________________________________________
>> FireBase-BR (www.firebase.com.br) - Hospedado em www.locador.com.br
>> Para saber como gerenciar/excluir seu cadastro na lista, use:
>> http://www.firebase.com.br/fb/artigo.php?id=1107
>> Para consultar mensagens antigas: http://firebase.com.br/pesquisa
>
>




Mais detalhes sobre a lista de discussão lista