Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Consulta de postagem e tags na mesma consulta


É melhor se você não optar por um group_concat solução porque não é confiável devido ao tamanho dos caracteres, tem um limite padrão de 1024 caracteres para concatenar, mas pode ser aumentado, o que é definido em manual mas você não pode confiar totalmente no limite definido, em vez disso, você pode lidar com isso em sua camada de aplicativo (php) como se estivesse buscando dados e em algum lugar onde deseja exibir postagens e suas tags relacionadas, você ainda pode usar sua consulta de junção com ordem por postagens agora a cada postagem pode ter mais de uma tag para que o conjunto de resultados tenha dados de posts duplicados devido a cada linha de post ter uma tag e outra linha com o mesmo post terá a segunda tag e assim por diante agora quando você percorrer seus resultados mostre cada post apenas uma vez por adicionando algum cheque
$this->db->select('p.*,t.*');
$this->db->from('posts p');
$this->db->join('tags_map tm', 't.id_post = p.id');
$this->db->join('tags t', 't.id = tm.id_tag');
$this->db->order_by('p.id asc,t.id asc');
$results = $this->db->get();

Na consulta acima eu adicionei t.* para selecionar todos os posts e suas tags relacionadas agora em loop $currentParent terá um id de postagem anterior em loop, verifique se é a mesma postagem e, em seguida, exiba suas tags se a condição retornar false, então é uma nova postagem de exibição de cabeçalho de postagem usando marcação (h1), selecionei todas as colunas de ambas as tabelas, mas você deve adicionar apenas o necessário colunas da tabela de tags e se a tabela de postagem e tag tiver colunas com o mesmo nome, na consulta, as definiu com um alias diferente
$currentParent = false;
foreach ($results as $post) {
    if ($currentParent != $post->id) {
        echo '<h1>' . $post->title . '</h1>';
        $currentParent = $post->id;
    }
    echo '<p>' . $post->name . '</p>'; /** here list tags info*/
    echo '<p>' . $post->tag_other_details . '</p>'; 
    ...
}

A marcação resultante será como
<h1>Post title 1</h1>
    <p>tag 1</p>
    <p>tag 2</p>
<h1>Post title 2</h1>
    <p>tag 3</p>...

Se você não estiver exibindo dados e estiver usando-os em algum outro lugar (serviço da web), ainda use uma consulta unida e transforme seus dados criando uma matriz/objeto, cada postagem tem uma matriz de suas tags relacionadas, algo como abaixo
$posts =array();
foreach ($results as $post) {
 $posts[$post->id]['title'] = $post->title;
 $posts[$post->id]['tags'][] =array('id' => $tag->id ,'name' =>$post->name);
}

há outra maneira que é altamente não recomendada get posts e em loop get tags executando query agora esta solução funcionará, mas envolverá consultas indesejadas para que haja uma consulta extra executada para cada postagem.

Agora, se você realmente quer ficar com group_concat abordagem para responder à sua pergunta I'm not sure if I can trust the order? há também uma maneira de adicionar order by em group_concat para que as tags concatenadas resultantes sejam ordenadas e para a segunda coluna você pode colocar os mesmos critérios de ordenação
$this->db->select('p.*,group_concat(t.name order by t.id) as thetags,
                       group_concat(t.relevance order by t.id) as therelevances');
$this->db->from('posts p');
$this->db->join('tags_map tm', 't.id_post = p.id');
$this->db->join('tags t', 't.id = tm.id_tag');
$this->db->group_by('p.id');