Jump to content
Omar~

Separar resultados com base de outra tabela

Recommended Posts

É o seguinte tenho duas tabelas aqui estão elas

Spoiler

CREATE TABLE IF NOT EXISTS `sectors` (
    `sector_id` int(11) NOT NULL AUTO_INCREMENT,
    `sector_status` CHAR(1) NOT NULL DEFAULT '0' COMMENT '0 = escondido, 1 = visivel',
    `sector_date` date NOT NULL,
    `sector_hash` varchar(100),
    `sector_title` varchar(100),
    `sector_link` varchar(100),
    `sector_icon` varchar(200),
    `sector_info` text,
    `sector_comment` text,
    PRIMARY KEY (`sector_id`)
) CHARACTER SET utf8 COLLATE utf8_unicode_ci;

 


CREATE TABLE IF NOT EXISTS `pages` (
    `page_id` int(11) NOT NULL AUTO_INCREMENT,
    `page_status` CHAR(1) NOT NULL DEFAULT '0' COMMENT '0 = escondido, 1 = visivel',
    `page_date` date NOT NULL,
    `page_hash` varchar(100),
    `page_title` varchar(100),
    `page_link` varchar(100),
    `page_sector` varchar(100),
    `page_content` text,
    PRIMARY KEY (`page_id`)
) CHARACTER SET utf8 COLLATE utf8_unicode_ci;

 

 

Então eu tenho uma tabela para setores e outra tabela para páginas.

As páginas são separadas de acordo com os setores existentes, uso para identificar o setor que a página pertence pela coluna page_sector

Que sempre é igual a coluna sector_hash da tabela de setores.

 

Agora ao problema, como eu faria a leitura da tabela de pages, separando as páginas com sua relação ao setor (Agrupando as páginas em seu setor). Certo, mas isso é só usar um ORDER BY, mas preciso regatar o título do setor, que logo está em outra tabela.

Mas então simples não é, é só fazer um select nas duas tabelas.....

Entra a dificuldade aqui pois estou com dificuldade de renderizar o HTML, a não ser que eu faça algumas gabiarras veja:

<?php
$selectA = new Select();
$selectA->setQuery('SELECT * FROM sectors');
$selectB = clone $selectA;
$selectB->setQuery('SELECT * FROM pages');
foreach ($selectA->result() as $sector) {
    echo '<br>-Setor : ' . $sector->sector_title . '<br>';
    foreach ($selectB->result() as $pages) {
        if ($pages->page_sector == $sector->sector_hash) {
            echo '<br>..... Página :' . $pages->page_title . '<br>';
        }
    }
    echo '<br>- Fim do setor '. $sector->sector_title .'<br>----------------<br>';
}

 

O que no momento com os registros de testes imprime isso:

Spoiler


-Setor : Setor 1
..... Página : Primeiro Conteúdo para o setor visível 1
..... Página :sssSegundo ConteúdoSetor 1
..... Página :João e Maria
..... Página :454545
..... Página :sasjlakjslajl
..... Página :Em caminho de Paca Tatú Caminha dentro
..... Página :jhhjhjhj
..... Página :kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk
..... Página :11111111111111111111111
- Fim do setor Setor 1


----------------
-Setor : Setor 2
..... Página :Setor 2 Content
..... Página :ggggggggggggggggg
- Fim do setor Setor 2


----------------
-Setor : Setor de teste 3
..... Página :Página Oculta
- Fim do setor Setor de teste 3


----------------
-Setor : lkdsjalksjalsjal
- Fim do setor lkdsjalksjalsjal


----------------

 

Seria assim mesmo a renderização final, setor por setor e páginas dentro de cada setor correspondente.

Mas aí que entra a X da questão.

- Precisei acessar 2 vezes o banco // Teria como fazer através de 1 select só?

foreach dentro de foreach  // Isso é muito esquisito ao meu ver

 

Alguma sugestão de como dar para fazer diferente?

Share this post


Link to post
Share on other sites

Olá @Omar~, tranquilo?

 

Muita gente nessa situação faz uma consulta de "pages" para cada "sector", o que é ineficiente.

Você fez certinho sim, com duas consultas e dois foreach (afinal, são dois conjuntos de dados). Não há nenhuma gambiarra aí não.

 

Faço apenas uma ressalva:

7 horas atrás, Omar~ disse:

foreach ($selectB->result() as $pages) {

Esse método result() será chamado múltiplas vezes. Não sei o que ele faz (se ele apenas recupera o resultado, ou se ele executa a consulta e depois o recupera), mas para deixar mais eficiente você poderia deixar ele fora do loop, assim:

$pages_result = $selectB->result();

foreach ($selectA->result() as $sector) {
    echo '<br>-Setor : ' . $sector->sector_title . '<br>';
    foreach ($pages_result as $pages) {

Ao menos que result() seja um método que utilize yield (generators) ou ponteiros internamente (como o Phalcon)... daí isso não faria diferença.

 

EDIT: Eu acabei ignorando o JOIN do banco, pois eu sei que você o conhece e deve ter considerado usar. É uma boa opção para economizar uma consulta, mas como você deve ter percebido não seria uma forma natural de exibir os dados para o seu caso e você acabaria não fugindo dos dois foreach.

Dependendo do caso (volume de dados, quantidade de colunas, etc) pode valer a pena, mas tomar esse caminho como primeira opção seria meramente uma "otimização precipitada", e isso é nocivo na construção de software. Além disso a diferença de performance deve ser muito pouco expressiva.

 

Outro ponto importante é que esses dados são previsivelmente cacheáveis, então essa consulta pode ser feita apenas 1 vez a cada X tempo se você inserir uma camada de cache entre o banco e seu app, o que acaba tornando qualquer otimização desnecessária. Exemplos: APC, Memcached, Dynamodb...

Edited by Matheus Tavares
Complementar resposta

Share this post


Link to post
Share on other sites

Valeu Matheus. Passei o dia inteiro pensando em diversas alternativas, algumas até boas, mas nenhuma além do que transcrevi valeu a pena.

A melhor alternativa foi fazer uma consulta só usando JOIN então criar 2 arrays, uma só armazenando os resultado ferente ao setor outro array para os dados das páginas.

Ao qual de qualquer forma não dava para escapar se varrer os arrays com foreach, além do mais achei que fazer assim seria "ficar inventando moda".

 

O método result apenas devolve um atributo que está armazenando um array com os resultados da consulta

public function result() {
    if ($this->selectData) {
      return ($this->selectData);
    }
}

Ao qual esse atributo está armazenado o fetchAll() do resultado PDO

55 minutos atrás, Matheus Tavares disse:

Muita gente nessa situação faz uma consulta de "pages" para cada "sector", o que é ineficiente.

Sim isso seria  completamente inviável de ser feito.

Então imagina 150 setores e 300 páginas. Ou seja 45.000 consultas de uma só vez.

 

Enfim vou dar como sanado, mesmo porque sempre fiz da forma que falei, só queria saber se tinha alguma outra forma de fazer muito mais, com muito menos

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Similar Content

    • By Rodrigo5468
      Olá a todos(as), boa tarde!
       
      Tenho uma Query e um pequeno código em PHP para mostrar os resultados em uma tabela, mas estão repetindo os resultados da Query. Gostaria de uma solução, ou uma gambiarra para isso.
      Query
      SELECT DISTINCT b.ID AS "ID", b.Character AS "Personagem", b.Money AS "DinMao", b.BankMoney AS "DinBanco", b.Savings2 AS "DinPoupa", c.houseOwner AS "IDono", SUM(c.houseMoney) AS "DinCasa" FROM characters b INNER JOIN houses c ON (b.ID = c.houseOwner) ORDER BY ((b.Money+b.BankMoney+b.Savings2+c.houseMoney)) DESC LIMIT 0, 1000 PHP
      if(mysqli_num_rows($q) > 0) { while($r = $q->fetch_assoc()) { //Código da Tabela } }  
      Observação:
      Quando eu removo a seguinte parte da minha Query que é: SUM(c.houseMoney) AS "DinCasa" e deixo assim: c.houseMoney AS "DinCasa"
      Os dados da minha tabela repetem, não sei o motivo e/ou a circunstância disso. Mas peço a ajuda de vocês para solucionar. Vale ressaltar que (ID e houseOwner) tem os mesmos valores, só o valor da casa que recebe o valor do ID, e ele pode ter quantas casa ele quiser, e se ele tiver cinco casas, mostrará o resultado cinco resultados na minha tabela, como posso resolver isso?
       
       
      Meu muito obrigado desde já.
    • By eduardo_barros
      Boa tarde,
       
      Possuo uma aplicação rodando em Laravel com Db Mysql.
       
      Porem um cliente solicitou que o nosso sistema ficasse gravando informações no banco de dados SQL deles e vice e versa, só que o sistema deles não tem API, nesse caso vamos executar as queries do banco banco deles do nosso lado lendo e escrevendo, como funciona essa multiconexão de bancos dentro do laravel?
    • By peterstefan
      Olá, estou com uma query aqui e preciso pegar de 2 campos diferentes os dados diferente de 0,  mais quanto tento no AND ele somente traz um resultado, o OR ele traz um dos campos com o valor 0, teria alguma forma de pegar os dados diferente de 0 dos dois campus?
      preciso pegar o idOrganizador diferente de 0 e o idPiloto diferente de 0 
       
      SELECT * FROM boletos WHERE proc = 0 AND idOrganizador !='0' AND idPiloto ='0';  
    • By thiago009
      Sou novato na área, estou criando um site para praticar, o meu problema está na página contatos. O objetivo é que ele salve os dados do formulário num arquivo do access. Sei que não é o ideal, como estou começando na área, acho que é melhor aprender assim para depois estudar outras formas.
      Criei um comando no SQL que intitulei de "grava", o nome do meu arquivo do access é "banco" e o html é contato.
      Tentei também validar os campos com java, mas não deu certo e exclui os códigos que tinha colocado no início do html, se alguém puder me ajudar a fazer a validação.
      Isso não é um trabalho, estou fazendo para aprender.

      Segue link com os arquivos:
      https://etecspgov-my.sharepoint.com/:f:/g/personal/thiago_cunha35_etec_sp_gov_br/EioK0B6ZHaNNlJ6zZWSXSfUB7PwxWfp-R5ulmqZOr1Hlpg?e=v51d7i
       
       
      Agradeço quem puder ajudar,
       

      Muito Obrigado.
    • By mamotinho
      oi pessoal estou com um problema , não estou conseguindo passar todos os valores o foreach no json_encode() alguém poderia me ajudar, eu estou tentando monta um mecanismo de refresh em tempo real de uma lista de notificação veja abaixo:
       
      <script type="text/javascript"> function make_call() { // Fazendo requisição AJAX $j.post('teste.php', function (frase) { // Exibindo frase $j('#listas').html('<i>' + frase + '</i>'); }, 'JSON'); setTimeout(function(){ make_call(); }, 5000); } </script>
      Aqui é o arquivo que quero enviar para a div #lists
       
      <?php require("conexao/directory.php"); $notificar = $db->query("select TOP 5 * from Techi7CP.dbo.cabal_notificacao_geral order by regdate desc"); $notificacao = $notificar->fetchAll(); $count_notificacao = abs($notificar->rowCount()); if($count_notificacao==0){ echo '<li style="text-align:center;">não existe notificações no momento.</li>'; }else{ foreach($notificacao as $notif){ $consulta_conta = $db->query("select * from account.dbo.cabal_auth_table where UserNum='".$notif['usernum']."'")->fetchObject(); switch($notif['acao']){ case 'logadopremiado' : echo ' <li><a class="black-text" href="#!"><span class="material-icons icon-bg-circle red small">redeem</span>'.$notif['jogador'].' ganhou no Logado Premiado</a> <time class="media-meta grey-text darken-2" datetime="2015-06-12T20:50:48+08:00"> '.Data::ExibirTempoDecorrido(date("Y-m-d H:i:s.B", strtotime($notif['regdate']))).'</time> </li>'; break; case 'mudarsenha' : echo ' <li><a class="black-text" href="#!"><span class="material-icons icon-bg-circle teal small">vpn_key</span>'.$consulta_conta->Nome.' alterou sua senha</a> <time class="media-meta grey-text darken-2" datetime="2015-06-12T20:50:48+08:00"> '.Data::ExibirTempoDecorrido(date("Y-m-d H:i:s.B", strtotime($notif['regdate']))).'</time> </li>'; break; case 'distribuirpontos' : echo ' <li><a class="black-text" href="#!"><span class="material-icons icon-bg-circle cyan small">control_point</span>'.$notif['jogador'].' distribuiu seus pontos</a> <time class="media-meta grey-text darken-2" datetime="2015-06-12T20:50:48+08:00"> '.Data::ExibirTempoDecorrido(date("Y-m-d H:i:s.B", strtotime($notif['regdate']))).'</time> </li>'; break; case 'girodasorte' : echo ' <li><a class="black-text" href="#!"><span class="material-icons icon-bg-circle brown small">star_border</span>'.$consulta_conta->Nome.' usou o giro da sorte</a> <time class="media-meta grey-text darken-2" datetime="2015-06-12T20:50:48+08:00"> '.Data::ExibirTempoDecorrido(date("Y-m-d H:i:s.B", strtotime($notif['regdate']))).'</time> </li>'; break; case 'sistematpoint' : echo ' <li><a class="black-text" href="#!"><span class="material-icons icon-bg-circle green small">golf_course</span>'.$notif['jogador'].' recebeu seu tpoint por clique</a> <time class="media-meta grey-text darken-2" datetime="2015-06-12T20:50:48+08:00"> '.Data::ExibirTempoDecorrido(date("Y-m-d H:i:s.B", strtotime($notif['regdate']))).'</time> </li>'; break; case 'combo' : echo ' <li><a class="black-text" href="#!"><span class="material-icons icon-bg-circle amber small">videogame_asset</span>'.$notif['jogador'].' fez '.$notif['ExtraDetalhes'].' em sua primeira vez</a> <time class="media-meta grey-text darken-2" datetime="2015-06-12T20:50:48+08:00"> '.Data::ExibirTempoDecorrido(date("Y-m-d H:i:s.B", strtotime($notif['regdate']))).'</time> </li>'; break; } } } ?> como eu faria para ser exibido todos os resultados registrados com o json_encode().
×

Important Information

Ao usar o fórum, você concorda com nossos Terms of Use.