sql >> Base de Datos >  >> RDS >> Mysql

MySQL no admite la cláusula de límite dentro de una subselección, ¿cómo puedo hacer eso?

SELECT... LIMIT no es compatible con las subconsultas, me temo, así que es hora de explotar la magia de la autounión:

SELECT article.*
FROM article
JOIN (
    SELECT a0.category_id AS id, MIN(a2.article_id) AS lim
    FROM article AS a0
    LEFT JOIN article AS a1 ON a1.category_id=a0.category_id AND a1.article_id>a0.article_id
    LEFT JOIN article AS a2 ON a2.category_id=a1.category_id AND a2.article_id>a1.article_id
    GROUP BY id
) AS cat ON cat.id=article.category_id
WHERE article.article_id<=cat.lim OR cat.lim IS NULL
ORDER BY article_id;

El bit en el medio está calculando la identificación del tercer artículo con la identificación más baja para cada categoría al intentar unir tres copias de la misma tabla en orden de identificación ascendente. Si hay menos de tres artículos para una categoría, las uniones a la izquierda garantizarán que el límite sea NULO, por lo que el WHERE externo también debe tomar ese caso.

Si su requisito de "top 3" podría cambiar a "top n" en algún momento, esto comienza a ser difícil de manejar. En ese caso, es posible que desee reconsiderar la idea de consultar primero la lista de categorías distintas y luego unir las consultas por categoría.

ETA:Pedidos en dos columnas:eek, ¡nuevos requisitos! :-)

Depende de lo que quiera decir:si solo está tratando de ordenar los resultados finales, puede golpearlo al final sin problema. Pero si necesita usar este orden para seleccionar qué tres artículos se recogerán, las cosas son mucho más difíciles.

Estamos utilizando una autounión con '<' para reproducir el efecto que tendría 'ORDER BY article_id'. Desafortunadamente, aunque puede hacer 'ORDENAR POR a, b', no puede hacer '(a, b)<(c, d)'... tampoco puedes hacer 'MIN(a, b)'. Además, en realidad estaría ordenando por tres columnas, es fijo, publicado y article_id, porque debe asegurarse de que cada valor de pedido sea único, para evitar que se devuelvan cuatro o más filas.

Mientras que podrías invente su propio valor ordenable con algún entero bruto o combinación de cadenas de columnas:

LEFT JOIN article AS a1
ON a1.category_id=a0.category_id
AND HEX(a1.issticky)+HEX(a1.published_at)+HEX(a1.article_id)>HEX(a0.issticky)+HEX(a0.published_at)+HEX(a0.article_id)

esto se está poniendo increíblemente feo, y los cálculos arruinarán cualquier posibilidad de usar los índices para hacer que la consulta sea eficiente. En ese momento, es mejor que simplemente haga las consultas LIMITadas por categoría por separado.