MySQL: devolver cero cuando no hay valor presente, categorizado mensualmente
-
20-09-2019 - |
Pregunta
Tengo las siguientes dos tablas que registran el gasto y proporcionan información de categoría de gastos:
Transacciones de tabla:
+-------+--------+--------+
| month | cat_id | amount |
+-------+--------+--------+
| 1 | 2 | 3 |
| 1 | 2 | 8 |
| 2 | 1 | 7 |
| 2 | 1 | 5 |
+-------+--------+--------+
Categorías de tabla:
+--------+-------------+
| cat_id | cat_desc |
+--------+-------------+
| 1 | Stock |
| 2 | Consumables |
+--------+-------------+
Lo que me gustaría es construir una consulta que muestre una suma de las cantidades para cada categoría, para cada mes, incluso si no hay gastos en esa categoría para ese mes como este:
+-------+-------------+--------+
| month | cat_desc | amount |
+-------+-------------+--------+
| 1 | Stock | 0 |
| 1 | Consumables | 11 |
| 2 | Stock | 12 |
| 2 | Consumables | 0 |
+-------+-------------+--------+
Sospecho que una unión externa necesitaría ser utilizada, pero aún no he encontrado una declaración para hacerlo.
Gracias por cualquier ayuda.
Solución
Este debería proporcionarle el resultado correcto. El interno seleccionado prepara una lista de todos los meses combinados con todas las categorías, y el LEFT JOIN
Maneja el resto.
SELECT t.month, t.cat_desc, COALESCE(SUM(t2.amount), 0) amount
FROM (
SELECT DISTINCT t.month, c.cat_id, c.cat_desc
FROM categories c
CROSS JOIN transactions t
) t
LEFT JOIN transactions t2 ON ( t2.month = t.month AND t2.cat_id = t.cat_id )
GROUP BY t.month, t.cat_desc
El rendimiento puede ser mejor con lo siguiente (usando DISTINCT
Solo cuando sea necesario), pero tendrá que probar:
SELECT t.month, t.cat_desc, COALESCE(SUM(t2.amount), 0) amount FROM (
SELECT t.month, c.cat_id, c.cat_desc
FROM
(SELECT DISTINCT month FROM transactions) t
CROSS JOIN categories c
) t
LEFT JOIN transactions t2 ON ( t2.month = t.month AND t2.cat_id = t.cat_id )
GROUP BY t.month, t.cat_desc
Otros consejos
SELECT c.cat_id, c.cat_desc,t.month, SUM(t.amount)
FROM categories c
LEFT JOIN transactions t ON (t.cat_id = c.cat_id)
GROUP BY c.cat_id,t.month
SELECT c.cat_id, c.cat_desc,t.month, SUM(t.amount)
FROM categories c
LEFT JOIN transactions t ON (t.cat_id = c.cat_id)
GROUP BY t.month,c.cat_id
Order By t.month