Pregunta:
Fecha: 27-07-2017 03:05:00
(En Español)
y me devuelve las sumas de los dias asi

Mi problema es que por ejemplo el dia 02/07/2017 no hubo salidas, yo necesito que me muestre un 0 o NULL , como puedo hacer ??
Muchas Gracias
Votos: 0 - Respuestas: 24 - Vistas: 25 Compartir en: Google Facebook Twitter LinkedIn Link
¿Cómo hacer para que MySQL devuelva un 0 si no hay registro?[No resuelta]
Buen dia, tengo esta consulta :SELECT SUM(caja_hoy) as monto, DATE(fecha) mydate FROM salidas WHERE date(fecha) >= date('2017-07-1') AND date(fecha) <='2017-07-31' GROUP BY mydatey me devuelve las sumas de los dias asi

Mi problema es que por ejemplo el dia 02/07/2017 no hubo salidas, yo necesito que me muestre un 0 o NULL , como puedo hacer ??
Muchas Gracias
Votos: 0 - Respuestas: 24 - Vistas: 25 Compartir en: Google Facebook Twitter LinkedIn Link
Respuestas:
-
Fecha: 27-07-2017 10:45:21 Podrías compartir los datos de la imagen?
No se ve y no tengo idea de lo que te está devolviendo Votos: 0 - Link respuesta -
Fecha: 27-07-2017 10:59:56 Por ejemplo devuelve algo asi, pero en el dia 2017-07-02 no hubo registros por eso quiero que me devuelva un 0, sino se me saltea una columna en la grilla de la pantalla y se me desafan los datos
9300 2017-07-01
8642 2017-07-03
1750 2017-07-04
1100 2017-07-05
7194 2017-07-06
500 2017-07-07
1100 2017-07-08
360 2017-07-10
1234 2017-07-11
1393 2017-07-12
2140 2017-07-13 Votos: 0 - Link respuesta -
Fecha: 27-07-2017 11:13:24 Te faltaría para el 2 y el 9 de julio, correcto?
La consulta me parece que está bien y hasta ahora yo no sé si lo que pides se pueda hacer directo con una consulta. Lo que sí puedes hacer es con PHP iterar los resultados al recibirlos y desplegarlos adecuadamente.
Dado que ya defines el rango de fechas suena fácil ponerlo en un for.
Ya lo intentaste? Votos: 0 - Link respuesta -
Fecha: 27-07-2017 11:36:22 Hola, bastante interesante tu caso, la única solución que se me ocurre por ahora (y no es una muy elegante, pero funciona :P) es usar un procedimiento almacenado y una tabla temporal:
DELIMITER $$ DROP PROCEDURE IF EXISTS `sp_ReporteMontoSalidas`$$ CREATE DEFINER=`root`@`localhost` PROCEDURE `sp_ReporteMontoSalidas`(IN varStart DATE, IN varEnd DATE) BEGIN DECLARE varMonto DECIMAL(14,2); CREATE TEMPORARY TABLE IF NOT EXISTS tmp_results_reporte_monto_salidas (monto DECIMAL(14,2), mydate DATE); WHILE varStart <= varEnd DO SELECT COALESCE(SUM(caja_hoy), 0) INTO varMonto FROM salidas WHERE fecha = varStart; INSERT INTO tmp_results_reporte_monto_salidas SELECT varMonto, varStart; SET varStart = DATE_ADD(varStart, INTERVAL 1 DAY); END WHILE; SELECT * FROM tmp_results_reporte_monto_salidas; DROP TEMPORARY TABLE IF EXISTS tmp_results_reporte_monto_salidas; END$$ DELIMITER ;
CALL sp_ReporteMontoSalidas('2017-01-01', '2017-01-05')
Estos son los datos con los que cargue la tabla:

Y este es el resultado del procedimiento almacenado:

Suerte. Votos: 2 - Link respuesta -
Fecha: 29-07-2017 04:04:26 Definitivamente la respuesta de Jorge Zabala es la única opción si querés forzar un cero.
Igual tu clase que realiza las consultas puede hacer una validación sencilla. Si el resultset está vacío, devuelve cero. Votos: 0 - Link respuesta -
Fecha: 29-07-2017 05:45:39 Esperaba que hubiera alguna solución mas elegante y optima (solo trabajando con MySQL) XD Votos: 0 - Link respuesta
-
Fecha: 29-07-2017 06:01:16 Usa CASE
SELECT SUM(CASE WHEN caja_hoy IS NULL THEN 0 ELSE caja_hoy END) as monto, DATE(fecha) mydate FROM salidas WHERE date(fecha) >= date('2017-07-1') AND date(fecha) <='2017-07-31' GROUP BY mydateVotos: 0 - Link respuesta -
Fecha: 29-07-2017 06:39:00 Tom Vega, el problema consiste en que para que aparezca una fecha debe existir al menos un registro en esa fecha y el necesita que se incluyan todos los dias en el rango de fecha indicado, tengan registros o no, en caso de no tenerlos dar un cero, el cual ya puedes obtenerlo con un CASE o mas simple aun un COALESCE(SUM(col), 0).
Saludos. Votos: 1 - Link respuesta -
Fecha: 29-07-2017 06:45:41 Este ultimo con CASE, me gusta mas, pero no arroja datos, ya que no es NULL, sino que no existe, como puedo modificarlo ? Muchas Gracias a todos ! Votos: 0 - Link respuesta
-
Fecha: 29-07-2017 06:54:12 No es que necesite que me muestre si o si un 0, puede sr un NULL o cualquier cosa, lo importante es que no me saltee el dia sin mostar nada Votos: 0 - Link respuesta
-
Fecha: 29-07-2017 07:08:02 Uff ya entendí... como yo lo veía si estaba el registro solo que era nulo pq no tenía salidas... Votos: 0 - Link respuesta
-
Fecha: 29-07-2017 07:56:47 Ok, tras un poco de investigación dí con lo que ya pensaba debías hacer.. Crear una tabla "calendario" a la que harías right join, esto lo saqué de esta pregunta de stackoverflow y de este blog, lo simplifiqué un poco para no hacerlo tan extenso.
Primero ejecutas estos queries:
CREATE TABLE calendar_table ( dt DATE NOT NULL PRIMARY KEY, y SMALLINT NULL, m tinyint NULL, d tinyint NULL );
CREATE TABLE ints ( i tinyint );
INSERT INTO ints VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
INSERT INTO calendar_table (dt) SELECT DATE('2010-01-01') + INTERVAL a.i*10000 + b.i*1000 + c.i*100 + d.i*10 + e.i DAY FROM ints a JOIN ints b JOIN ints c JOIN ints d JOIN ints e WHERE (a.i*10000 + b.i*1000 + c.i*100 + d.i*10 + e.i) <= 11322 ORDER BY 1;
UPDATE calendar_table SET y = YEAR(dt), m = MONTH(dt), d = dayofmonth(dt);
Puedes ejecutarlos todos en una misma vez. El primero crea la tabla calendario, el segundo crea la tabla ints (necesaria para popular a calendario desde el mismo MySql), tercero carga los ints, el cuarto popula el calendario y el 5to (no es necesario, es sólo para tener acceso más directo al año mes y día) separa la fecha.
El cuantos días necesites lo puedes sacar de acá (en el ejemplo se está populando un calendario con fechas desde 01 enero 2010 hasta 31 diciembre 2040, osease 11322 días)
SELECT datediff('2040-12-31','2010-01-01');
Y modificas el 4to query dependiendo del número de días que se genere.
Ahora, mi query de prueba fue así:
SELECT SUM(CASE WHEN p.available_time_quantity IS NULL THEN 0 ELSE p.available_time_quantity END) as times, p.name, dateC.dt date from prices p right join calendar_table dateC ON dateC.dt = date(p.created_at) where dateC.dt BETWEEN '2017-07-25' AND '2017-07-30' GROUP BY dateC.dt
Si lo amoldamos al tuyo supongo que sería este:
SELECT SUM(CASE WHEN s.caja_hoy IS NULL THEN 0 ELSE s.caja_hoy END) as monto, DATE(s.fecha) mydate FROM salidas s RIGHT JOIN calendar_table c ON c.dt = DATE(s.fecha) WHERE c.dt BETWEEN '2017-07-01' AND '2017-07-31' GROUP BY mydate
Me comentas si funciona pls :D
P.D: El crear el calendario es algo que haces una sola vez, deberías incluirlo de ahora en adelante en todos tus proyectos de este tipo.. Nunca se sabe cuando necesitas unas buenas fechas definidas :D
Ya luego para cualquier reporte que necesites, es solo RIGHT JOIN a la mencionada tabla. Votos: 0 - Link respuesta -
Fecha: 29-07-2017 08:02:33 Estimado Jorge Zabala,
gracias por enseñarme tan maravillosa función!
¡Oh COALESCE()! dónde habías estado toda mi vida? *-* Votos: 0 - Link respuesta -
Fecha: 29-07-2017 08:42:30 Tom Vega, interesante solución, tener una tabla calendario generada, me parece mas tedioso respecto al hecho de necesitar mantener actualizado el calendario para asegurarte que exista el intervalo que necesitas (tal vez sea necesario cambiar ese insert por un insert or update para controlar el tema de llaves primarias repetidas). Me parece que en general resulta mas eficiente, mas aun si el reporte cruzara con tablas de gran tamanio (millones de registros para arriba :P).
Pdt. Algo similar fue mi reacción cuando encontré coalesce, es realmente util XD Votos: 0 - Link respuesta -
Fecha: 29-07-2017 11:06:58 Estimado Jorge,
Como comenté, la tabla calendario debería generarse y popularse una sola vez, al inicio del desarrollo sistema. Según el ejemplo, se están populando 30 años de fechas, y todos sabemos que la vida útil de un sistema es muchisimo menos que eso..
Cómo está definido puedes cargar un calendario desde el inicio de los tiempos hasta un absurdo año 3000 si gustas (realmente exagero hehe), claro, con la consecuencia de que tendrías cientos de miles de registros (1 por día).
Realmente la tabla calendario en este ejemplo se queda muy corta en cuanto al uso que se le da, pero estoy 100% seguro de que las aplicaciones son infinitas.
Saludos. Votos: 0 - Link respuesta -
Fecha: 03-08-2017 05:08:20 Esta Solucion es Algo radical y aunque se ve fea y es antiestetica, funciona ok y no necesita mantenimiento del calendario.
Se trata de una consulta derivada( o subconsulta) que envuelve la union de los dias del mes en 0 mas tu consulta.
La subconsulta reemplaza los dias en 0 por los valores en que los hubiere.
Los dias que sobrepasen del mes se eliminan en el Where de la subconsulta
///****** version para que te copies !!!
select max(monto) as monto ,mydate
FROM(
select 0 as monto , '2017-07-01' as mydate
union all
select 0 as monto, ADDDATE('2017-07-01' , INTERVAL 1 DAY) as mydate
union all
select 0 as monto, ADDDATE('2017-07-01' , INTERVAL 2 DAY) as mydate
union all
select 0 as monto, ADDDATE('2017-07-01' , INTERVAL 3 DAY) as mydate
union all
select 0 as monto, ADDDATE('2017-07-01' , INTERVAL 4 DAY) as mydate
union all
select 0 as monto, ADDDATE('2017-07-01' , INTERVAL 5 DAY) as mydate
union all
select 0 as monto, ADDDATE('2017-07-01' , INTERVAL 6 DAY) as mydate
union all
select 0 as monto, ADDDATE('2017-07-01' , INTERVAL 7 DAY) as mydate
union all
select 0 as monto, ADDDATE('2017-07-01' , INTERVAL 8 DAY) as mydate
union all
select 0 as monto, ADDDATE('2017-07-01' , INTERVAL 9 DAY) as mydate
union all
select 0 as monto, ADDDATE('2017-07-01' , INTERVAL 10 DAY) as mydate
union all
SELECT SUM(caja_hoy) as monto, fecha as mydate
FROM salidas
WHERE fecha >= '2017-07-01' AND fecha <='2017-07-31'
GROUP BY fecha
) as deriv
WHERE mydate >= '2017-07-01' AND mydate <='2017-07-31'
GROUP BY mydate Votos: 0 - Link respuesta -
Fecha: 03-08-2017 05:39:59 Hola Carlos,
Algunos inconvenientes que veo en tu solución es que te toca realizar una sub consulta para cada día, no todos los meses tienen 31 días, así que también se debe conocer eso con anticipación, más aun si el reporte es de varios meses y no solo uno. Ademas, creo resultaría demasiado pesado si se trabajan con muchos registros (millones de transacciones). Creo que la opción de Tom Vega de tener una tabla calendario seria la mas optima hasta ahora ya que solo realizas un left|right join simple. Votos: 1 - Link respuesta -
Fecha: 03-08-2017 06:01:22 Carlos Serias tan amable de poner la consulta mysql directamente, no logro poder probarla . Muchas Gracias Votos: 0 - Link respuesta
-
Fecha: 03-08-2017 07:05:13 Jorge: yo avise que el metodo no era el optimo, estoy de acuerdo con vos.
Te comento que la subconsulta es una sola, el cuerpo esta formado por una union que no requiere un proceso real de la base sino que hace uso de la funcion addate. para crear los renglones
El que se pase de los dias del mes no es una preocupacion, porque la consulta real esta dentro de las fechas verdaderas y los registros en 0 que superen el mes son eliminados en el where que agregue al final.
Es feo. lo ideal es hacer un procedimiento almacenado y llamarlo con los parametros del mes, pero a veces te encontras con restricciones, o estas metiendo mano en bases de otros, o son soluciones Para YA! ....y tenes que usar formas algo mas radicales en la solucion
Leando: en unas horas te la reescribo completa. Votos: 0 - Link respuesta -
Fecha: 03-08-2017 07:33:54 Para este tipo de asuntos existe SQL Fiddle.
Pueden compartir ejemplos ahí. Votos: 0 - Link respuesta -
Fecha: 03-08-2017 15:37:36 Leandro: En la respuesta anterior te deje corregida la consulta para que la pruebes, como veras le puse hasta el dia 10 para que no me quede tan largo, aunque seria hasta el 31. (suponiendo que tu rango es mensual)
Es obvio que ese es el resultado final, si estas trabajando con php la resolucion de esa consulta se hace con un while que agrega a una string los renglones aumentados de acuendo a la fecha de inicio y final de la consulta. Votos: 0 - Link respuesta -
Fecha: 05-08-2017 04:01:05 Buen dia Carlos, no me fue efectiva la consulta, me arroja lo siguiente:
Votos: 0 - Link respuesta
-
Fecha: 07-08-2017 02:59:03 Leandro: el problema que tenes esta en que la orden Group no te esta funcionando debido a que tu campo de calculo es datetime y la de los 0 es solo date. corregi la linea
SELECT SUM(caja_hoy) as monto, fecha as mydate
por
SELECT SUM(caja_hoy) as monto, DATE(fecha) as mydate
y te va a funcionar Votos: 1 - Link respuesta -
Para participar activamente de la comunidad primero debes autenticarte, ingresa al sistema.Iniciar Sesión
