none
Agrupar por meses aunque no tenga movimiento RRS feed

  • Pregunta

  • Buen dia, agradeceria me apoyen con la siguiente consulta :

    Tengo una tabla Ventas, con campos: 

    FechaVenta, DOC, Importe, IdCliente.

    Necesito efectuar dos consultas :

    1. La primera para determinar un resumen de ventas por mes, hice la consulta con el nombre del mes y todo; el problema de suscita cuando en un mes no hay ventas, entonces ese mes se salta. Como puedo hacer para que el mes que no tiene movimiento salga en cero.

    2. La segunda, obtener un resumen de ventas por cliente, hice el group by por cliente, y lo sucede lo mismo, se salta el mes que el cliente no ha consumido.

    Agradecere cualquier orientacion o idea de como lograrlo. Gracias.


    Armando

    domingo, 15 de septiembre de 2019 20:14

Respuestas

  • Armando,

    Cómo se declaró la columna FechaVenta: ¿date? ¿datetime? ¿otra?

    ¿Cual es la versión de SQL Server?

    ---

    1. La primera para determinar un resumen de ventas por mes

    -- código #1 v2
    declare @Mes_Inicial tinyint, @Año_Inicial smallint, @Mes_Final tinyint, @Año_Final smallint;
    set @Mes_Inicial= __;
    set @Año_Inicial= ____;
    set @Mes_Final= __;
    set @Año_Final= ____;
    
    --
    declare @Fecha1 datetime, @Fecha2 datetime;
    set @Fecha1= datefromparts (@Año_Inicial, @Mes_Inicial, 1);
    set @Fecha2= datefromparts (@Año_Final, @Mes_Final, 1);
    set @Fecha2= dateadd (month, +1, @Fecha2);
    
    --
    with 
    Período as (
    SELECT @Fecha1 as Fecha, 
           year (@Fecha1) as Año, 
           month (@Fecha1) as Mes
    union all
    SELECT dateadd (month, +1, Fecha), 
           year (dateadd (month, +1, Fecha)), 
           month (dateadd (month, +1, Fecha))
      from Período
      where Fecha < @Fecha2
    ),
    aggVentas as (
    SELECT year (FechaVenta) as Año, month (FechaVenta) as Mes, 
           sum (Importe) as suma_Importe
      from Ventas
      where (FechaVenta >= @Fecha1 and FechaVenta < @Fecha2)
      group by year (FechaVenta), month (FechaVenta)
    )
    SELECT P.Año, P.Mes, coalesce (V.suma_Importe, 0) as suma_Importe
      from Período as P
           left join aggVentas as V on V.Año = P.Año and V.Mes = P.Mes
      where P.Fecha < @Fecha2;

    Donde está ___ reemplace con el valor correspondiente.

     

    y

    2. La segunda, obtener un resumen de ventas por cliente, (...)

    -- código #2 v2
    declare @Mes_Inicial tinyint, @Año_Inicial smallint, @Mes_Final tinyint, @Año_Final smallint;
    set @Mes_Inicial= __;
    set @Año_Inicial= ____;
    set @Mes_Final= __;
    set @Año_Final= ____;
    
    --
    declare @Fecha1 datetime, @Fecha2 datetime;
    set @Fecha1= datefromparts (@Año_Inicial, @Mes_Inicial, 1);
    set @Fecha2= datefromparts (@Año_Final, @Mes_Final, 1);
    set @Fecha2= dateadd (month, +1, @Fecha2);
    
    --
    with 
    Período as (
    SELECT @Fecha1 as Fecha, 
           year (@Fecha1) as Año, 
           month (@Fecha1) as Mes
    union all
    SELECT dateadd (month, +1, Fecha), 
           year (dateadd (month, +1, Fecha)), 
           month (dateadd (month, +1, Fecha))
      from Período
      where Fecha < @Fecha2
    ),
    Cliente as (
    SELECT distinct idCliente
      from Ventas
      where (FechaVenta >= @Fecha1 and FechaVenta < @Fecha2) ), aggVentas_Cliente as ( SELECT idCliente, year (FechaVenta) as Año, month (FechaVenta) as Mes, sum (Importe) as suma_Importe from Ventas where (FechaVenta >= @Fecha1 and FechaVenta < @Fecha2) group by idCliente, year (FechaVenta), month (FechaVenta) ) SELECT C.idCliente, P.Año, P.Mes, coalesce (V.suma_Importe, 0) as suma_Importe from Cliente as C cross join Período as P left join aggVentas_Cliente as V on V.idCliente = C.idCliente and V.Año = P.Año and V.Mes = P.Mes where P.Fecha < @Fecha2;

     Donde está ___ reemplace con el valor correspondiente.
     

    En ambos códigos SQL utilicé CTE para construir un código SQL modular, fácil de entender y sencillo de mantener: Programação modular com expressões de tabela.

     


    José Diz     Belo Horizonte, MG - Brasil     [query performance tuning: Porto SQL]


    Este conteúdo é fornecido sem garantias de qualquer tipo, seja expressa ou implícita.

    domingo, 15 de septiembre de 2019 20:54
  • Gracias Jose Diz, voy a probarlo.. una consulta que es esta parte
             aggVentas_Cliente
    Es la CTE (common table expression) que calcula las compras mensuales de cada cliente.

    José Diz     Belo Horizonte, MG - Brasil     [query performance tuning: Porto SQL]


    Este conteúdo é fornecido sem garantias de qualquer tipo, seja expressa ou implícita.

    miércoles, 18 de septiembre de 2019 17:10

Todas las respuestas

  • Armando,

    Cómo se declaró la columna FechaVenta: ¿date? ¿datetime? ¿otra?

    ¿Cual es la versión de SQL Server?

    ---

    1. La primera para determinar un resumen de ventas por mes

    -- código #1 v2
    declare @Mes_Inicial tinyint, @Año_Inicial smallint, @Mes_Final tinyint, @Año_Final smallint;
    set @Mes_Inicial= __;
    set @Año_Inicial= ____;
    set @Mes_Final= __;
    set @Año_Final= ____;
    
    --
    declare @Fecha1 datetime, @Fecha2 datetime;
    set @Fecha1= datefromparts (@Año_Inicial, @Mes_Inicial, 1);
    set @Fecha2= datefromparts (@Año_Final, @Mes_Final, 1);
    set @Fecha2= dateadd (month, +1, @Fecha2);
    
    --
    with 
    Período as (
    SELECT @Fecha1 as Fecha, 
           year (@Fecha1) as Año, 
           month (@Fecha1) as Mes
    union all
    SELECT dateadd (month, +1, Fecha), 
           year (dateadd (month, +1, Fecha)), 
           month (dateadd (month, +1, Fecha))
      from Período
      where Fecha < @Fecha2
    ),
    aggVentas as (
    SELECT year (FechaVenta) as Año, month (FechaVenta) as Mes, 
           sum (Importe) as suma_Importe
      from Ventas
      where (FechaVenta >= @Fecha1 and FechaVenta < @Fecha2)
      group by year (FechaVenta), month (FechaVenta)
    )
    SELECT P.Año, P.Mes, coalesce (V.suma_Importe, 0) as suma_Importe
      from Período as P
           left join aggVentas as V on V.Año = P.Año and V.Mes = P.Mes
      where P.Fecha < @Fecha2;

    Donde está ___ reemplace con el valor correspondiente.

     

    y

    2. La segunda, obtener un resumen de ventas por cliente, (...)

    -- código #2 v2
    declare @Mes_Inicial tinyint, @Año_Inicial smallint, @Mes_Final tinyint, @Año_Final smallint;
    set @Mes_Inicial= __;
    set @Año_Inicial= ____;
    set @Mes_Final= __;
    set @Año_Final= ____;
    
    --
    declare @Fecha1 datetime, @Fecha2 datetime;
    set @Fecha1= datefromparts (@Año_Inicial, @Mes_Inicial, 1);
    set @Fecha2= datefromparts (@Año_Final, @Mes_Final, 1);
    set @Fecha2= dateadd (month, +1, @Fecha2);
    
    --
    with 
    Período as (
    SELECT @Fecha1 as Fecha, 
           year (@Fecha1) as Año, 
           month (@Fecha1) as Mes
    union all
    SELECT dateadd (month, +1, Fecha), 
           year (dateadd (month, +1, Fecha)), 
           month (dateadd (month, +1, Fecha))
      from Período
      where Fecha < @Fecha2
    ),
    Cliente as (
    SELECT distinct idCliente
      from Ventas
      where (FechaVenta >= @Fecha1 and FechaVenta < @Fecha2) ), aggVentas_Cliente as ( SELECT idCliente, year (FechaVenta) as Año, month (FechaVenta) as Mes, sum (Importe) as suma_Importe from Ventas where (FechaVenta >= @Fecha1 and FechaVenta < @Fecha2) group by idCliente, year (FechaVenta), month (FechaVenta) ) SELECT C.idCliente, P.Año, P.Mes, coalesce (V.suma_Importe, 0) as suma_Importe from Cliente as C cross join Período as P left join aggVentas_Cliente as V on V.idCliente = C.idCliente and V.Año = P.Año and V.Mes = P.Mes where P.Fecha < @Fecha2;

     Donde está ___ reemplace con el valor correspondiente.
     

    En ambos códigos SQL utilicé CTE para construir un código SQL modular, fácil de entender y sencillo de mantener: Programação modular com expressões de tabela.

     


    José Diz     Belo Horizonte, MG - Brasil     [query performance tuning: Porto SQL]


    Este conteúdo é fornecido sem garantias de qualquer tipo, seja expressa ou implícita.

    domingo, 15 de septiembre de 2019 20:54
  • Gracias por responder.

    La columna fechaventa se declaro como datetime, sql version 2014.


    Armando

    lunes, 16 de septiembre de 2019 4:41
  • La columna fechaventa se declaro como datetime

    Armando, ya he cambiado los códigos SQL #1 y #2 para tratar los datos como datetime.

    El código SQL #2 considera a los clientes que tuvieron venta en el período. Si desea que todos los clientes registrados aparezcan en la lista, puede utilizar la tabla de clientes en lugar de la CTE Cliente.


    José Diz     Belo Horizonte, MG - Brasil     [query performance tuning: Porto SQL]


    Este conteúdo é fornecido sem garantias de qualquer tipo, seja expressa ou implícita.

    lunes, 16 de septiembre de 2019 10:10
  • Gracias Jose Diz, voy a probarlo.. una consulta que es esta parte 
    aggVentas_Cliente 

    Armando

    miércoles, 18 de septiembre de 2019 17:04
  • Gracias Jose Diz, voy a probarlo.. una consulta que es esta parte
             aggVentas_Cliente
    Es la CTE (common table expression) que calcula las compras mensuales de cada cliente.

    José Diz     Belo Horizonte, MG - Brasil     [query performance tuning: Porto SQL]


    Este conteúdo é fornecido sem garantias de qualquer tipo, seja expressa ou implícita.

    miércoles, 18 de septiembre de 2019 17:10