Límite de MySQL con relación de muchos a muchos
Pregunta
Dado un esquema para la implementación de etiquetas
ARTÍCULO ItemId, ItemContent
TAG TagId, TagName
ITEM_TAG ItemId, TagId
¿Cuál es la mejor manera de limitar la cantidad de ELEMENTOS que se devolverán al seleccionar con etiquetas?
SELECT i.ItemContent, t.TagName FROM item i
INNER JOIN ItemTag it ON i.id = it.ItemId
INNER JOIN tag t ON t.id = it.TagId
es, por supuesto, la forma más fácil de recuperarlos, pero el uso de una cláusula límite se desglosa, ya que obtienes un duplicado de todos los elementos para cada etiqueta, que cuenta para el número de filas en LIMIT.
Solución
Mi segunda solución utiliza una función MySQL GROUP_CONCAT () para combinar todas las etiquetas que coinciden con el elemento en una cadena separada por comas en el conjunto de resultados.
SELECT i.ItemContent, GROUP_CONCAT(t.TagName ORDER BY t.TagName) AS TagList
FROM item AS i
INNER JOIN ItemTag AS it ON i.id = it.ItemId
INNER JOIN tag AS t ON t.id = it.TagId
GROUP BY i.ItemId;
La función GROUP_CONCAT () es una característica de MySQL, no es parte de SQL estándar.
Otros consejos
Tal vez algo como
select i.ItemContent, t.TagName from (SELECT ItemId, ItemContent FROM item limit 10) i
INNER JOIN ItemTag it ON i.ItemId = it.ItemId --You will miss tagless items here!
INNER JOIN tag t ON t.id = it.TagId
Mi primera sugerencia es usar una subconsulta para generar la lista de ID de artículo y devolver los artículos que coincidan con esa ID de artículo. Pero esto no incluye el TagName en su conjunto de resultados. Enviaré una respuesta por separado con otra solución.
SELECT i.ItemContent
FROM item AS i
WHERE i.id IN (
SELECT it.ItemId
FROM ItemTag AS it
INNER JOIN tag AS t ON (t.id = it.TagId)
WHERE t.TagName IN ('mysql', 'database', 'tags', 'tagging')
);
Esta es una subconsulta no correlacionada, por lo que un buen motor SQL debería tenerlo en cuenta y ejecutarlo solo una vez.
También puedes usar Distinct / Group By:
SELECCIONE DISTINCT TagID, TagName FROM ((TAG T
INTERNO UNIRSE A ITEM_TAG I_T EN T.TagID = I_T.TagID)
ÍNDICE DE UNIÓN INTERNA I EN I_T.ItemID = I.ItemID)
GROUP BY TagID, TagName