php - soporta - optimizar consultas lentas mysql
Consulta de publicaciones y etiquetas en la misma consulta (3)
Tengo 3 tablas con esos campos relevantes
publicaciones (id, título)
etiquetas (id, nombre)
tags_map (id, id_post, id_tag)
Lo intento así:
$this->db->select(''posts.*,tags.name'');
$this->db->from(''posts'');
$this->db->join(''tags_map'', ''tags.id_post = posts.id'');
$this->db->join(''tags'', ''tags.id = tags_map.id_tag'');
$this->db->group_by(''posts.id''); // I can comment this line and same result
Esto parece, pero incluso cuando hay más de un registro de tags_map, solo devuelve uno,
¿Cómo puedo devolverlos todos, en una consulta?
-editar-
Lo solucioné un poco, pero requiere manejo de php
$this->db->select(''posts.*,group_concat(tags.name) as thetags'');
Esto retrotraería un campo thethags = ''tag1, tag2, tag3''
Pero me gustaría obtener otros archivos en la tabla de etiquetas ...
Y, por ejemplo:
$this->db->select(''posts.*,group_concat(tags.name) as ''thetags'',group_concat(tags.relevance) as ''therelevances'');
No estoy seguro si puedo confiar en la orden?
Pruebe el siguiente código:
$this->db->select(''pt.*,group_concat(tg.name order by tg.id) as thetags,group_concat(tg.relevance order by tg.id) as therelevances'');
$this->db->from(''posts pt'');
$this->db->join(''tags_map tm'', ''tg.id_post = pt.id'');
$this->db->join(''tags tg'',''tg.id =tm.id_tag'');
$this->db->group_by(''pt.id'');
Creo que debería ser consultado así
$this->db->select(''posts.*, tags.name'');
$this->db->from(''tags_map'');
&this->db->join(''posts'', ''tags_map.id_post = posts.id'');
$this->db->join(''tags'', ''tags_map.id_tag = tags.id'');
al usar join, debe usar la relación uno a muchos, en este caso la tabla tags_map sirve como la tabla de unión que sirve la relación de varios a uno con la tabla de publicaciones y etiquetas
Es mejor si no busca una solución group_concat
porque no es confiable debido a la longitud del carácter, tiene un límite predeterminado de 1024 caracteres para concatenar, pero se puede aumentar, que se define en manual, pero no puede confiar plenamente en el límite definido en su lugar. puede manejarlo en su capa de aplicación (php) como si estuviera buscando datos y en algún lugar desea mostrar publicaciones y sus etiquetas relacionadas, puede usar su consulta de unión con pedido por publicaciones ahora cada publicación puede tener más de una etiqueta para que el resultado se establezca tendrá datos duplicados de publicaciones debido a que cada fila de publicaciones tendrá una etiqueta y otra fila con la misma publicación tendrá una segunda etiqueta, y así sucesivamente ahora, cuando revise sus resultados, muestre cada publicación solo una vez agregando algún control
$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();
En la consulta anterior he agregado t.*
Para seleccionar todas las publicaciones y sus etiquetas relacionadas ahora en loop $currentParent
tendrá una identificación previa de la publicación en la verificación de bucle si es una misma publicación y luego mostrará sus etiquetas si la condición es falsa y luego aparece una nueva publicación publicar el encabezado usando markup (h1), he seleccionado todas las columnas de ambas tablas, pero debe agregar solo las columnas necesarias de la tabla de etiquetas y si las tablas de publicación y etiqueta tienen columnas del mismo nombre, en la consulta las definió con un 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>'';
...
}
El marcado 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>...
Si no muestra datos y lo está usando en algún otro lugar (servicio web) y aún utiliza una consulta combinada y transforma sus datos creando una matriz / objeto, cada publicación tiene una matriz de sus etiquetas relacionadas, algo así como a continuación
$posts =array();
foreach ($results as $post) {
$posts[$post->id][''title''] = $post->title;
$posts[$post->id][''tags''][] =array(''id'' => $tag->id ,''name'' =>$post->name);
}
hay otra manera en la que no se recomienda obtener publicaciones y en las etiquetas de obtención de bucle mediante la ejecución de consultas; ahora esta solución funcionará pero implicará consultas no deseadas para que se ejecute una consulta adicional para cada publicación.
Ahora bien, si realmente quiere seguir con el enfoque de group_concat
para responder a su pregunta, I''m not sure if I can trust the order?
También hay una forma de agregar order by
en group_concat
para que se group_concat
las etiquetas concatenadas resultantes y para la segunda columna puede colocar los mismos criterios de ordenamiento.
$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'');