Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Suche nach Posts und Tags in derselben Abfrage

Es ist besser, wenn Sie sich nicht für einen group_concat Lösung Da es aufgrund der Zeichenlänge nicht zuverlässig ist, hat es ein Standardlimit von 1024 Zeichen zum Verketten, aber es kann erhöht werden, was in manual Sie können sich jedoch nicht vollständig auf das definierte Limit verlassen. Stattdessen können Sie es in Ihrer Anwendungsschicht (php) so handhaben, als würden Sie Daten abrufen, und irgendwo, wo Sie Posts und die zugehörigen Tags anzeigen möchten, können Sie jetzt für jeden Post immer noch Ihre Join-Abfrage mit der Reihenfolge nach Posts verwenden kann mehr als ein Tag haben, so dass der Ergebnissatz doppelte Postdaten enthält, da jede Post-Zeile ein Tag hat und eine andere Zeile mit demselben Post ein zweites Tag und so weiter, wenn Sie jetzt Ihre Ergebnisse durchgehen, zeigen Sie jeden Post nur einmal an ein Häkchen hinzufügen

$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();

In der obigen Abfrage habe ich t.* hinzugefügt um alle Beiträge und die zugehörigen Tags jetzt in der Schleife $currentParent auszuwählen Wird eine vorherige Post-ID in Schleife haben, prüfen Sie, ob es sich um denselben Post handelt, und zeigen Sie dann seine Tags an, wenn die Bedingung falsch zurückgibt, dann ist es ein neuer Post, der die Post-Überschrift mit Markup (h1) anzeigt. Ich habe alle Spalten aus beiden Tabellen ausgewählt, aber Sie sollten nur die erforderlichen hinzufügen Spalten aus der Tag-Tabelle und wenn Post- und Tag-Tabelle Spalten mit demselben Namen haben, dann wurden sie in der Abfrage mit unterschiedlichen Aliasnamen

definiert
$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>'; 
    ...
}

Das resultierende Markup sieht aus wie

<h1>Post title 1</h1>
    <p>tag 1</p>
    <p>tag 2</p>
<h1>Post title 2</h1>
    <p>tag 3</p>...

Wenn Sie keine Daten anzeigen und sie woanders verwenden (Webdienst), verwenden Sie dennoch eine verbundene Abfrage und transformieren Sie Ihre Daten, indem Sie ein Array/Objekt erstellen. Jeder Beitrag hat ein Array seiner zugehörigen Tags, etwa wie unten

$posts =array();
foreach ($results as $post) {
 $posts[$post->id]['title'] = $post->title;
 $posts[$post->id]['tags'][] =array('id' => $tag->id ,'name' =>$post->name);
}

Es gibt einen anderen Weg, der sehr nicht empfohlen wird Posts und In-Loop-Tags abrufen, indem Sie jetzt eine Abfrage ausführen. Diese Lösung funktioniert, führt jedoch zu unerwünschten Abfragen, sodass für jeden Post eine zusätzliche Abfrage ausgeführt wird.

Wenn Sie jetzt wirklich bei group_concat bleiben wollen Vorgehensweise zur Beantwortung Ihrer Frage I'm not sure if I can trust the order? Es gibt auch eine Möglichkeit, order by hinzuzufügen in group_concat damit die resultierenden verketteten Tags geordnet werden, und für die zweite Spalte können Sie dieselben Sortierkriterien

eingeben
$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');