1

Tengo la siguiente consulta que me devuelve los ingresos y egresos por mes.

Si el producto tiene movimiento lo trae pero sino ha tenido movimiento ¿como hago para traerlo?

Es un reporte de inventarios mensual

SELECT *, 
    (B1*costo_producto) AS TOTAL,
    fecha,
    (sum(cantidad)-sum(cantidadEgreso))as IngresoMes,
    sum(cantidadEgreso) as egresoMes,
    ( (sum(cantidad)-sum(cantidadEgreso)) * costo_producto) as ValIngMes,
    (sum(cantidadEgreso) * costo_producto) as ValEgMes,
    ven_com 
FROM products,und 
    inner join ingresosegresos 
where date(fecha) BETWEEN '2021-06-01' AND '2021-06-31' 
    and products.und_pro=und.id_und 
    and products.id_producto=ingresosegresos.id_producto 
    and ven_com<>12 
GROUP BY `products`.`id_producto` DESC

me devuelte esto

introducir la descripción de la imagen aquí

Estas son las tablas

CREATE TABLE `ingresosegresos` (
  `id_detalle` int(11) NOT NULL,
  `id_cliente` int(10) NOT NULL,
  `id_vendedor` int(10) NOT NULL,
  `numero_factura` int(11) NOT NULL,
  `ot` varchar(20) NOT NULL,
  `id_producto` varchar(100) NOT NULL,
  `cantidad` decimal(10,0) NOT NULL,
  `cantidadEgreso` int(100) NOT NULL,
  `precio_venta` decimal(10,6) NOT NULL,
  `tienda` int(2) NOT NULL,
  `activo` int(1) NOT NULL,
  `ven_com` int(2) NOT NULL,
  `fecha` datetime NOT NULL,
  `precio_compra` decimal(10,2) NOT NULL,
  `tipo_doc` int(2) NOT NULL,
  `inv_ini` decimal(10,2) NOT NULL,
  `moneda` decimal(4,2) NOT NULL,
  `folio` varchar(5) NOT NULL,
  `nome` varchar(100) NOT NULL,
  `Renglon` varchar(100) DEFAULT NULL,
  `Lote` varchar(100) NOT NULL,
  `Orden` varchar(100) NOT NULL,
  `Serie_fac` varchar(100) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;

CREATE TABLE `products` (
  `id_producto` int(11) NOT NULL,
  `codigo_producto` char(20) NOT NULL,
  `nombre_producto` text NOT NULL,
  `status_producto` tinyint(1) NOT NULL,
  `date_added` datetime NOT NULL,
  `precio_producto` decimal(10,2) NOT NULL,
  `costo_producto` decimal(10,6) NOT NULL,
  `mon_costo` decimal(4,2) NOT NULL,
  `mon_venta` int(2) NOT NULL,
  `max` varchar(50) NOT NULL,
  `desc_corta` varchar(50) NOT NULL,
  `color` varchar(1000) NOT NULL,
  `b1` decimal(10,2) NOT NULL,
  `b2` decimal(10,2) NOT NULL,
  `b3` decimal(10,2) NOT NULL,
  `b4` decimal(10,2) NOT NULL,
  `b5` decimal(10,2) NOT NULL,
  `b6` decimal(10,2) NOT NULL,
  `cat_pro` int(2) NOT NULL,
  `pro_ser` int(2) NOT NULL,
  `foto1` varchar(100) NOT NULL,
  `foto2` varchar(100) NOT NULL,
  `foto3` varchar(100) NOT NULL,
  `foto4` varchar(100) NOT NULL,
  `fecha_caducidad` date NOT NULL,
  `pre_web` decimal(10,2) NOT NULL,
  `descripcion` text NOT NULL,
  `descripcion1` text NOT NULL,
  `megusta` int(10) NOT NULL,
  `nomegusta` int(10) NOT NULL,
  `precio2` decimal(10,2) NOT NULL,
  `precio3` decimal(10,2) NOT NULL,
  `und_pro` int(3) NOT NULL,
  `barras` varchar(20) NOT NULL,
  `dcto` decimal(4,2) NOT NULL,
  `min` decimal(10,2) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;


CREATE TABLE `und` (
  `id_und` int(2) NOT NULL,
  `nom_und` varchar(100) NOT NULL,
  `cod_und` varchar(4) NOT NULL,
  `xml_und` varchar(4) NOT NULL,
  `etiqueta` varchar(5) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Marcos
  • 30,626
  • 6
  • 28
  • 63

2 Answers2

1

La estrategia que recomiendo seguir en estos casos, es hacer primero el resumen y hasta después hacer un outer join de la tabla para la que se quiere que aparezcan todos los registros con este resultado. Por ejemplo, a continuación mi ejemplo mínimo y verificable:

select   products.codigo_producto
       , products.nombre_producto
       , resumen.Ingresos
       , resumen.Egresos
       , resumen.MovimientoNeto
  from products
       left join (select   id_producto
                         , sum(Cantidad) Ingresos
                         , sum(cantidadEgreso) Egresos
                         , sum(Cantidad - cantidadEgreso) MovimientoNeto
                    from ingresosegresos
                   where date(fecha) between '2021-06-01' and '2021-06-31'
                   group by id_producto
                 ) resumen
              on resumen.id_producto = products.id_producto

Puede que no haya interpretado bien el significado de los campos de tu tabla, intenté leyendo el query, pero no se auto-explican y no encuentro consistencia ni en la forma de nombrarlos ni en los tipos de datos, por eso hago la aclaración.

No esperes que la consulta funcione al copiar y pegar, pero si lees la explicación y te esfuerzas por entender la idea, serás capaz de hacer las adaptaciones necesarias para que te entregue la información que necesitas.

Dado que es un ejemplo mínimo, he quitado intencionalmente la tabla und de la consulta, considero que integrarla debiera resultarte trivial.

Si utilizas mySQL 8 o superior, puedes valerte de un CTE lo cual, en mi opinión, deja un resultado más legible y fácil de mantener:

with 
resumen as (
select   id_producto
       , sum(Cantidad) Ingresos
       , sum(cantidadEgreso) Egresos
       , sum(Cantidad - cantidadEgreso) MovimientoNeto
  from ingresosegresos
 where date(fecha) between '2021-06-01' and '2021-06-31'
 group by id_producto
)
select   products.codigo_producto
       , products.nombre_producto
       , resumen.Ingresos
       , resumen.Egresos
       , resumen.MovimientoNeto
  from products
       left join resumen on resumen.id_producto = products.id_producto
jachguate
  • 25,659
  • 7
  • 35
  • 61
1

Tu query tiene algunas inconsistencias como:

  • El DESC en el GROUP BY (DESC keyword se utiliza para ordernar por un campo de manera descedente no para agrupar).
  • Agrupas solo por el id del producto y seleccionas ingresosegresos.fecha en el SELECT (cuando puede haber muchas fechas por cada producto), no me queda claro si también quieres agrupar por fecha o quieres que los cálculos incluyan todos los ingresosegresos alcanzados por la clásula WHERE.

Para que te liste todos los productos deberías hacer un LEFT JOIN con und y ingresosegresos (en lugar de un INNER JOIN). Hice una subquery para ingresosegresos con las restricciones que tenías en el WHERE, así trae un subconjunto de registros en función de tus restricciones.

Es dificil hacer la query sin conocer bien el modelo de datos y que datos necesitas, pero basandome en tu query algo así te podría servir:

SELECT 
       products.id_producto,
       B1 * costo_producto AS TOTAL,
       SUM(COALESCE(cantidad, 0)) - SUM(COALESCE(cantidadEgreso, 0)) AS IngresoMes, 
       SUM(COALESCE(cantidadEgreso, 0)) AS egresoMes, 
       (SUM(COALESCE(cantidad, 0)) - SUM(COALESCE(cantidadEgreso, 0))) * costo_producto AS ValIngMes, 
       SUM(COALESCE(cantidadEgreso, 0)) * costo_producto as ValEgMes 

FROM products
LEFT JOIN und ON products.und_pro = und.id_und
LEFT JOIN (SELECT *
           FROM ingresosegresos
           WHERE date(fecha) BETWEEN '2021-06-01' AND '2021-06-31' AND ven_com <> 12) AS ingresosegresos ON products.id_producto = ingresosegresos.id_producto
GROUP BY products.id_producto, products.B1, products.costo_producto;
nachospiu
  • 2,454
  • 2
  • 3
  • 14