Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

Matheus Tavares

Left join retornando apenas uma linha

Recommended Posts

Olá pessoal. Tudo bem?

Bom.. tenho as seguintes tabelas:

 

mysql> select * from `empresas`;
+----+-------+-----------+-------+------------+----------------+
| id | tipo  | logotipo  | nome  | grupo      | cnpj           |
+----+-------+-----------+-------+------------+----------------+
|  8 | Lazer | troll.jpg | Teste | Pespi Cola | 99999313412312 |
+----+-------+-----------+-------+------------+----------------+

mysql> select * from `empresas_contatos`;
+----+---------+------------+--------------+------------+
| id | empresa | rotulo     | email        | telefone   |
+----+---------+------------+--------------+------------+
|  1 |       8 | Principal  | x@xxx.co.co  | 5112121212 |
|  2 |       8 | Financeiro | fin@y.net    | 5012121212 |
+----+---------+------------+--------------+------------+

 

E gostaria de recuperar ambas simultaneamente utilizando LEFT JOIN:

 

mysql> select `e`.`nome`, `e`.`grupo`, `c`.* from `empresas` `e` 
    -> left join `empresas_contatos` `c` on
    -> `c` . `empresa` = `e` . `id`;
+-------+------------+------+---------+------------+-------------+------------+
| nome  | grupo      | id   | empresa | rotulo     | email       | telefone   |
+-------+------------+------+---------+------------+-------------+------------+
| Teste | Pespi Cola |    1 |       8 | Principal  | x@xxx.co.co | 5112121212 |
| Teste | Pespi Cola |    2 |       8 | Financeiro | fin@y.net   | 5012121212 |
+-------+------------+------+---------+------------+-------------+------------+

 

O problema é o seguinte: Há dados sendo recuperados que são desnecessários. Minha tabela é bem maior que o exemplo acima, e se a empresa tiver 2 contatos (email/telefone) e 2 endereços (é outra tabela, que não postei por ser desnecessário), significa que vou recuperar 4 linhas: todas com o mesmo "nome", "grupo", "logotipo", "empresa", etc.

 

No exemplo acima, a empresa de id 8 tinha 2 contatos e por isso o mysql retornou duas linhas, cada uma para um contato da empresa, porém com os dados da empresa repetidos. Eu sei que é o comportamento normal, mas quero evitar isso, da seguinte forma:

 

A cada coluna do contato que ele recuperar, adicionar um index no final, exemplo: email1, email2, telefone1, telefone2, e dessa forma recuperar somente uma linha.

 

Por exemplo: tendo como base a consulta acima, gostaria de retornar somente UMA linha, com as seguintes colunas: nome, grupo, id1, id2, empresa1, empresa2, rotulo1, rotulo2, email1, email2, telefone1, telefone2.

E caso houvesse mais um contato, existiria um email3, telefone3, etc.

 

Talvez eu esteja complicando o simples, mas fiquei curioso com essa situação e gostaria de solucionar.

 

Abraço!

Compartilhar este post


Link para o post
Compartilhar em outros sites

Pessoal, consegui da seguinte forma:

 

select e.nome, e.grupo, g.empresa,
  MAX(CASE WHEN rownum = 1 THEN g.rotulo END) rotulo1,
  MAX(CASE WHEN rownum = 2 THEN g.rotulo END) rotulo2,
  MAX(CASE WHEN rownum = 1 THEN g.email END) email1,
  MAX(CASE WHEN rownum = 2 THEN g.email END) email2,
  MAX(CASE WHEN rownum = 1 THEN g.telefone END) telefone1,
  MAX(CASE WHEN rownum = 2 THEN g.telefone END) telefone2
from (
    select id,empresa,email,telefone,rotulo,
        @running:=if(@previous=empresa,@running,0) + 1 as rownum,
        @previous:=empresa
    from empresas_contatos t
      JOIN (SELECT @running:= 0) r
      JOIN (SELECT @previous:= 0) s
) g JOIN empresas e on g.empresa = e.id
GROUP BY e.nome, e.grupo, g.empresa

Retorno:

 

 

+-------+-------+---------+---------+---------+---------+--------+------------+------------+
| nome  | grupo | empresa | rotulo1 | rotulo2 | email1  | email2 | telefone1  | telefone2  |
+-------+-------+---------+---------+---------+---------+--------+------------+------------+
| Teste | Pespi |       8 | Vendas  | Suporte | x@x.x   | y@y.y  | 5112121212 | 5012121212 |
+-------+-------+---------+---------+---------+---------+--------+------------+------------+

 

 

O problema é que preciso definir manualmente quantas linhas de contatos existem.

 

Estou pensando em utilizar GROUP_CONCAT() para facilitar as coisas, mas caso alguém tenha alguma sugestão, pode mandar!

 

###################### EDIT: #########################

 

Bom pessoal, acabei utilizando o GROUP_CONCAT() e gambiarrizando no PHP mesmo. Segue a solução que adotei, caso ajude alguém:

 

<?php
$sql = sprintf('
    SELECT
        `e` . *,
        GROUP_CONCAT( DISTINCT
            `c`.`rotulo`, \'%s\',
            `c`.`email`, \'%1$s\',
            `c`.`telefone`
            ORDER BY `c`.`id` ASC
            SEPARATOR \'%s\'
        ) `contatos`,
        GROUP_CONCAT( DISTINCT
            IFNULL( `end`.`latitude` , \'\' ), \'%1$s\',
            IFNULL( `end`.`longitude` , \'\' ), \'%1$s\',
            `end`.`cep`, \'%1$s\',
            `end`.`estado`, \'%1$s\',
            `end`.`cidade`, \'%1$s\',
            `end`.`bairro`, \'%1$s\',
            `end`.`endereco`, \'%1$s\',
            IFNULL( `end`.`endereco_numero` , \'\' ), \'%1$s\',
            IFNULL( `end`.`complemento` , \'\' )
            ORDER BY `end`.`principal` DESC
            SEPARATOR \'%2$s\'
        ) `enderecos`
    FROM `empresas` `e`
    LEFT JOIN `empresas_enderecos` `end` ON
        `end` . `empresa` = `e` . `id`
    LEFT JOIN `empresas_contatos` `c` ON
        `c` . `empresa` = `e` . `id`
    %s
',
$field_separator = ';;', $row_separator = '==',
(int)$id ? 'WHERE `e` . `id` = ' . (int)$id : '' );


foreach( $data = $this->query( $sql ) as $index => $row ):
    # Contatos
    $row_name = 'contatos';
    $contatos = explode( $row_separator, $row[ $row_name ] );
    if( !empty( $contatos ) ):
        unset( $data[ $index ][ $row_name ] );
        foreach( $contatos as $c_row ):
            $arr = &$data[ $index ][ $row_name ][];
            list(
                $arr[ 'rotulo' ], $arr[ 'email' ], $arr[ 'telefone' ]
            ) = explode( $field_separator, $c_row );
        endforeach;
    endif;
    
    # Endereços
    $row_name = 'enderecos';
    $enderecos = explode( $row_separator, $row[ $row_name ] );
    if( !empty( $enderecos ) ):
        unset( $data[ $index ][ $row_name ] );
        foreach( $enderecos as $e_row ):
            $arr = &$data[ $index ][ $row_name ][];
            list(
                $arr[ 'latitude' ], $arr[ 'longitude' ],
                $arr[ 'cep' ], $arr[ 'estado' ],
                $arr[ 'cidade' ], $arr[ 'bairro' ],
                $arr[ 'endereco' ], $arr[ 'endereco_numero' ],
                $arr[ 'complemento' ]
            ) = explode( $field_separator, $e_row );
        endforeach;
    endif;
endforeach;


pr( $data );die;

Retorno:

Array
(
    [0] => Array
        (
            [id] => 8
            [tipo] => Lazer
            [logotipo] => troll.jpg
            [nome] => Teste
            [grupo] => Pespi Cola
            [cnpj] => 99999313412312
            [quartos] => 
            [dias_cancelamento] => 
            [valor_min_parcelamento] => 
            [max_parcelas] => 0
            [diferencia_criancas] => 0
            [idade_criancas] => 
            [contatos] => Array
                (
                    [0] => Array
                        (
                            [telefone] => 5112121212
                            [email] => contato@parangaricotirimirruaro.co.co
                            [rotulo] => Principal
                        )


                    [1] => Array
                        (
                            [telefone] => 5012121212
                            [email] => financeiro@heheehehhehe.net
                            [rotulo] => Financeiro
                        )


                    [2] => Array
                        (
                            [telefone] => 0800111111
                            [email] => homem@cueca.com
                            [rotulo] => Técnico
                        )


                )


            [enderecos] => Array
                (
                    [0] => Array
                        (
                            [complemento] => Ap 15
                            [endereco_numero] => 332
                            [endereco] => Rua das Flores
                            [bairro] => Centro
                            [cidade] => 8213
                            [estado] => 24
                            [cep] => 88015700
                            [longitude] => 
                            [latitude] => 
                        )


                    [1] => Array
                        (
                            [complemento] => 
                            [endereco_numero] => 666
                            [endereco] => Rua dos Albinos
                            [bairro] => Paraíso
                            [cidade] => 8555
                            [estado] => 23
                            [cep] => 01010101
                            [longitude] => 
                            [latitude] => 
                        )


                )


        )


)

Outra opção seria usar UNION ALL, mas seria uma gambiarra ainda maior, pois os campos da tabela pai (`empresa`), teriam que ser selecionados na mesma quantidade dos da tabela filha (`empresa_contatos` / `empresas_enderecos`).

 

[]'s

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.