none
Calcular datos por semana RRS feed

  • Pregunta

  • Buenas Tardes amigos

    Les traigo un nuevo reto

    Necesito calcular la cantidad de ventas por semana de cada articulo

    les muestro como tengo la estructura de mi tabla

    En esta imagen puse un mes para ver como se presenta los datos y lo que hago es agrupar por producto y sumar la cantidad vendida

    Entonces como puedo hacer para calcular las ventas por semana, de todo un año

    se puede?

    saludos


    ruben

    • Cambiado Sergio Parra sábado, 16 de junio de 2018 10:12 pregunta consultas SQL
    viernes, 15 de junio de 2018 14:56

Respuestas

  • Si quieres ir planteandolo es como así

    SELECT D.CODIGO, MAX(O.SEMANA1), MAX(O.SEMANA2)...... 
    FROM (
    SELECT D.CODIGO, 
    SUM(CASE WHEN  WEEK(FECHAENVIO)=0 THEN D.RONGSHULIANG END ) AS SEMANA1,
    SUM(CASE WHEN  WEEK(FECHAENVIO)=1 THEN D.RONGSHULIANG END ) AS SEMANA2,
    SUM(CASE WHEN  WEEK(FECHAENVIO)=2 THEN D.RONGSHULIANG END ) AS SEMANA3,
    SUM(CASE WHEN  WEEK(FECHAENVIO)=3 THEN D.RONGSHULIANG END ) AS SEMANA4,
    SUM(CASE WHEN  WEEK(FECHAENVIO)=4 THEN D.RONGSHULIANG END ) AS SEMANA5,
    SUM(CASE WHEN  WEEK(FECHAENVIO)=5 THEN D.RONGSHULIANG END ) AS SEMANA6,
    SUM(CASE WHEN  WEEK(FECHAENVIO)=6 THEN D.RONGSHULIANG END ) AS SEMANA7,
    SUM(CASE WHEN  WEEK(FECHAENVIO)=7 THEN D.RONGSHULIANG END ) AS SEMANA8,
    SUM(CASE WHEN  WEEK(FECHAENVIO)=8 THEN D.RONGSHULIANG END ) AS SEMANA9,
    SUM(CASE WHEN  WEEK(FECHAENVIO)=9 THEN D.RONGSHULIANG END ) AS SEMANA10
    
    FROM 
       POEE P
    INNER JOIN 
       PEDIDOMOV D ON P.PEDIDOKEY = D.PEDIDOKEY
     WHERE
       FECHAENVIO >= '20180101' AND FECHAENVIO < '20180201'
    GROUP BY D.CODIGO, WEEK(FECHAENVIO)
    ) AS O
    
    order by D.codigo

    Esto es de memoria sin abrir el gestor, aunque seguro que te vale


    • Marcado como respuesta Ruben Lezcano miércoles, 20 de junio de 2018 10:27
    miércoles, 20 de junio de 2018 9:22

Todas las respuestas

  • Chicos he probado esto y me da este resultado

    Pero yo espero esto

    algo así


    ruben

    viernes, 15 de junio de 2018 16:19
  • o en c# como lo podría hacer

    saludos


    ruben

    viernes, 15 de junio de 2018 16:24
  • Chicos es posible hacer esto que comento?

    saludos


    ruben

    lunes, 18 de junio de 2018 14:22
  • Hola ruben:

    Si es posible, voy a leer tu código, que se ve muy mal.

    Cuando pegues código, que es lo mejor, pues lo podemos reutilizar utiliza el botón que tienes a tal efecto.

    lunes, 18 de junio de 2018 19:44
  • Hola Rubén:

    Te voy a poner primero una semana por simpleza, ya que la estructura de tus tablas no esta nada clara, y las imágenes se ven bastante regular, para poder sacar una conclusión.

    Entiendo que tu tabla navmp es la cabecera de tus pedidos y tu tabla txgl es el detalle (lineas de pedido)

    SELECT D.CODIGO, SUM(D.RONGSHULIANG) AS UNIDADES, DATEPART(wk,FECHAENVIO) AS NUMSEMANA FROM NAVMP.POEE P INNER JOIN TXGL.PEDIDOMOV D ON P.PEDIDOPKEY = D.PEDIDOPKEY WHERE FECHAENVIO >= '20180101' AND FECHAENVIO < '20180201' GROUP BY D.CODIGO, DATEPART(wk,FECHAENVIO)

    order by d.codigo, DATEPART(wk,FECHAENVIO)

    Si esto te funciona. Pasaremos al siguiente nivel.

    lunes, 18 de junio de 2018 20:13
  • Hola Rubén:

    Ya no me acordaba que tu no trabajas con Sql server, que lo haces con mysql. Por cierto desconozco por las imágenes que entorno utilizas, pero para postear, es muy util, y seguro que el mismo dispone de una herramienta, las opciones de incluir los scripts de creación de tabla. Yo en mysql utilizo el Workbench y al selecciónar una tabla pulsando el botón derecho sobre ella tiene la opción de Send to Sql Editor, Create Statement.  Ese script que genera ayuda a entender lo que solicitas.

    /*EN MYSQL, LA ÚNICA DIFERENCIA, ES QUE LA OBTENCIÓN DE LA SEMANA, VA POR LA FUNCIÓN WEEK */
    SELECT D.CODIGO, SUM(D.RONGSHULIANG) AS UNIDADES, WEEK(FECHAENVIO) AS NUMSEMANA
    FROM 
       NAVMP.POEE P
    INNER JOIN 
       TXGL.PEDIDOMOV D ON P.PEDIDOPKEY = D.PEDIDOPKEY
     WHERE
       FECHAENVIO >= '20180101' AND FECHAENVIO < '20180201'
    GROUP BY D.CODIGO, WEEK(FECHAENVIO)
    
    order by d.codigo, WEEK(FECHAENVIO)
    /* EL TRATAMIENTO DE LAS FECHAS, ES IDÉNTICO, AUNQUE SI TE SIENTES MÁS CÓMODO SE PODRÍAN PONER EN FORMATO 2017-01-01 09:00:00' (ESTA OPCIÓN ES MÁS CONFLICTIVA) */

    martes, 19 de junio de 2018 6:45
  • Hola Javier

    He probado como me dices

    pero la columna semana no entiendo es el numero de semana?

    o significa que esta en dos semanas 

    saludos


    ruben

    martes, 19 de junio de 2018 10:25
  • No es el numero de semana.

    Si te funciona correctamente, porque la resolución de tus tablas es lo que te da mi consulta, por ejemplo si te coinciden loas filas para el Producto 03230004A para el periodo filtrado, para cada una de las semanas, entonces, pasamos a lo que tu pides que es las 52 semanas, pero en vez de por fila, por columna

    Saludos

    martes, 19 de junio de 2018 10:42
  • Javiiiiiiiiiiiiiiiiiiiiiiiiiii

    Perfecto ese es el calculo que necesito

    Ahora 

    Mira el resultado filtrado por un producto

    Como veras falta venta de la semana 2 

    Entonces quiero crear esa venta rellenando con la venta de la semana pasada o cuando tuvo movimiento

    eso se puede hacer en C# mejor no?

    saludos


    ruben

    martes, 19 de junio de 2018 10:56
  • Y como hacemos eso por columnas?

    saludos


    ruben

    martes, 19 de junio de 2018 11:49
  • Javi como vamos a hacer lo de por columna saludos

    ruben

    martes, 19 de junio de 2018 13:50
  • Hola Rubén: Esta tarde te daré las 52 columnas, pero confirmame, que es eso, que los datos te encajan.

    La semana 2 no aparece porque no hay pedidos para esa semana, para el codigo en cuestion.

    Saludos

    martes, 19 de junio de 2018 14:09
  • Si es eso Javi muchas gracias

    Y podríamos agregar también que si en la semana 2 esta vacío rellenamos con el de la semana anterior? eso se podría hacer? o vamos paso a paso 

    Muchas gracias


    ruben

    martes, 19 de junio de 2018 14:12
  • Se puede hacer
    martes, 19 de junio de 2018 14:23
  • vale Javi muchas gracias espero tu respuesta 

    millones de gracias de ante mano

    saludos


    ruben

    martes, 19 de junio de 2018 15:13
  • Observa el código que te he puesto, cuidado porque para evaluarlo, he tenido que camibar los nombres de tu esquema.tabla por solo tabla (POEE Y PEDIDOMOV). El analizador de consultas te mostrará los errores de denominación.

    SELECT D.CODIGO, 
    SUM(CASE WHEN  WEEK(FECHAENVIO)=0 THEN D.RONGSHULIANG END ) AS SEMANA1,
    SUM(CASE WHEN  WEEK(FECHAENVIO)=1 THEN D.RONGSHULIANG END ) AS SEMANA2,
    SUM(CASE WHEN  WEEK(FECHAENVIO)=2 THEN D.RONGSHULIANG END ) AS SEMANA3,
    SUM(CASE WHEN  WEEK(FECHAENVIO)=3 THEN D.RONGSHULIANG END ) AS SEMANA4,
    SUM(CASE WHEN  WEEK(FECHAENVIO)=4 THEN D.RONGSHULIANG END ) AS SEMANA5,
    SUM(CASE WHEN  WEEK(FECHAENVIO)=5 THEN D.RONGSHULIANG END ) AS SEMANA6,
    SUM(CASE WHEN  WEEK(FECHAENVIO)=6 THEN D.RONGSHULIANG END ) AS SEMANA7,
    SUM(CASE WHEN  WEEK(FECHAENVIO)=7 THEN D.RONGSHULIANG END ) AS SEMANA8,
    SUM(CASE WHEN  WEEK(FECHAENVIO)=8 THEN D.RONGSHULIANG END ) AS SEMANA9,
    SUM(CASE WHEN  WEEK(FECHAENVIO)=9 THEN D.RONGSHULIANG END ) AS SEMANA10
    
    FROM 
       POEE P
    INNER JOIN 
       PEDIDOMOV D ON P.PEDIDOKEY = D.PEDIDOKEY
     WHERE
       FECHAENVIO >= '20180101' AND FECHAENVIO < '20180201'
    GROUP BY D.CODIGO, WEEK(FECHAENVIO)
    
    order by d.codigo, WEEK(FECHAENVIO);
    
    

    Esta es la manera más fácil de trasponer filas por columnas, Si quieres las 52 semanas, continua....copia y pega.

    Fíjate que la semana empieza en 0 (max(fechaenvio)=0 y se llama 1. Creo que es así, pero eso tienes que verificarlo con tus datos.

    Y que el filtro fecha envio solo tiene un año, por tanto solo te dará datos, pertenecientes a 1 més.

    Si la consulta, tienes null, en los valores, tienes que poner esto.

    IFNULL(SUM(CASE WHEN  WEEK(FECHAENVIO)=9 THEN D.RONGSHULIANG END ),0) AS SEMANA10

    Ya contarás como te ha ido.

    martes, 19 de junio de 2018 15:52
  • Javi amigo no te olvides de mi 

    saludos


    ruben

    martes, 19 de junio de 2018 17:08
  • No te funciona el código del anterior mensaje????? tienes que comprobar los nombres y copiar y pegar

    SUM(CASE WHEN  WEEK(FECHAENVIO)=10 THEN D.RONGSHULIANG END ) AS SEMANA11,
    SUM(CASE WHEN  WEEK(FECHAENVIO)=11 THEN D.RONGSHULIANG END ) AS SEMANA12

    hasta 52


    • Editado Javi Fernández F martes, 19 de junio de 2018 17:38 error en la transcripcion
    martes, 19 de junio de 2018 17:37
  • Hola Javi

    Wooooo genio

    mira el resulta

    Pero se puede agrupar por código para que no genere tantos registros hay posibilidad

    saludos


    ruben

    miércoles, 20 de junio de 2018 8:17
  • Si claro. Al mediodía te lo plasmo.

    miércoles, 20 de junio de 2018 8:23
  • Muchas Gracias Javi

    saludos


    ruben

    miércoles, 20 de junio de 2018 8:56
  • Si quieres ir planteandolo es como así

    SELECT D.CODIGO, MAX(O.SEMANA1), MAX(O.SEMANA2)...... 
    FROM (
    SELECT D.CODIGO, 
    SUM(CASE WHEN  WEEK(FECHAENVIO)=0 THEN D.RONGSHULIANG END ) AS SEMANA1,
    SUM(CASE WHEN  WEEK(FECHAENVIO)=1 THEN D.RONGSHULIANG END ) AS SEMANA2,
    SUM(CASE WHEN  WEEK(FECHAENVIO)=2 THEN D.RONGSHULIANG END ) AS SEMANA3,
    SUM(CASE WHEN  WEEK(FECHAENVIO)=3 THEN D.RONGSHULIANG END ) AS SEMANA4,
    SUM(CASE WHEN  WEEK(FECHAENVIO)=4 THEN D.RONGSHULIANG END ) AS SEMANA5,
    SUM(CASE WHEN  WEEK(FECHAENVIO)=5 THEN D.RONGSHULIANG END ) AS SEMANA6,
    SUM(CASE WHEN  WEEK(FECHAENVIO)=6 THEN D.RONGSHULIANG END ) AS SEMANA7,
    SUM(CASE WHEN  WEEK(FECHAENVIO)=7 THEN D.RONGSHULIANG END ) AS SEMANA8,
    SUM(CASE WHEN  WEEK(FECHAENVIO)=8 THEN D.RONGSHULIANG END ) AS SEMANA9,
    SUM(CASE WHEN  WEEK(FECHAENVIO)=9 THEN D.RONGSHULIANG END ) AS SEMANA10
    
    FROM 
       POEE P
    INNER JOIN 
       PEDIDOMOV D ON P.PEDIDOKEY = D.PEDIDOKEY
     WHERE
       FECHAENVIO >= '20180101' AND FECHAENVIO < '20180201'
    GROUP BY D.CODIGO, WEEK(FECHAENVIO)
    ) AS O
    
    order by D.codigo

    Esto es de memoria sin abrir el gestor, aunque seguro que te vale


    • Marcado como respuesta Ruben Lezcano miércoles, 20 de junio de 2018 10:27
    miércoles, 20 de junio de 2018 9:22
  • Hola javi

    me da este error

    


    ruben

    miércoles, 20 de junio de 2018 9:57
  • Si en el O.codgo pongo MAX me muestra solo un registro

    donde puede estar el error Javi

    saludos


    ruben

    miércoles, 20 de junio de 2018 10:08
  • no o.codigo, no es max es el único que tiene que mostrar todos los códigos.

    miércoles, 20 de junio de 2018 10:12
  • tienes que poner group by o.codigo

    miércoles, 20 de junio de 2018 10:13
  • Siiiiiiiiiiiiiiiiiii

    Genio

    grande eres tío. Funciona a la perfección

    Por ultimo mira esta imagen

    Ese producto no tuvo venta en la seman 1 y semana2  pero si en la tres y la cuatro

    entonces podemos rellenar con el valor de la semana4 ?

    o eso se tiene que hacer por programación?

    saludos y mil millones de gracias


    ruben

    miércoles, 20 de junio de 2018 10:27
  • Hola Rubén puedes utilizar Coalesce....pero la sentencia te va a resultar un poco rollo.

    https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#function_coalesce

    Fíjate en el ejemplo. para cada columna tienes que poner, las otras columnas.

    Te vendría bien implementar IFNULL(max(oSemana1),0) para que tu vista no trabaje con nulos.

    Un saludo

    miércoles, 20 de junio de 2018 11:30
  • Hola Javier voy a crear un nuevo post con esta pregunta a ver si hay alguna solución por programación

    Muchas gracias Javier

    saludos


    ruben

    miércoles, 20 de junio de 2018 13:11
  • Javi

    Estaba mirando esto que me recomiendas y creo que ahí esta la solución pero como puedo aplicarlo?

    me podrías guiar, como agrego la comparación a lo que has echo?

    saludos


    ruben

    miércoles, 20 de junio de 2018 13:38
  • por ejemplo

    SELECT D.CODIGO, COALESCE(MAX(O.SEMANA1),MAX(O.SEMANA2)......) AS SEMANA1, 
    COALESCE(MAX(O.SEMANA2),MAX(O.SEMANA3),MAX(O.SEMANA4)....) AS 
    SEMANA2,
    COALESCE(MAX(O.SEMANA3), MAX(O.SEMANA4).....
    
    

    personalmente no me gusta nada.

    Yo creo que es mucho más bonito devolver un 0 que es realmente lo que has pedido en esa semana, puesto que devolver lo que has pedido en semanas posteriores, para mí es dar una información que te puede llevar a entuertos.

    Tambien lo puedes hacer en la capa de la vista, if columna0==0 then columna1....que te generará un código más legible.

    Saludos

    miércoles, 20 de junio de 2018 14:15
  • Hola Javi mira he probado como me dices pero me remplaza todos los resultados te muestro

    Este es el resultado bueno


    Este es el resuldato despues de agregar el COALESCE

    Ha rellenado los valores que estaban en NULL o 0 esta bien peroooo

    El primer registro por ejemplo la semana1 tiene 0 yo necesito que coja el resultado de la semana 3 y me lo agregara en la semana 1

    por que no cojo el resultado de la semana 2 pues por que tiene que ser el siguiente que tiene valor 

    es posible hacer eso?

    saludos


    ruben

    jueves, 21 de junio de 2018 9:32
  • Hola Rubén:

    select o.CODIGO, COALESCE(o.SEMANA1, o.SEMANA2,o.SEMANA3,o.SEMANA4,o.SEMANA5,o.SEMANA6,o.SEMANA7,o.SEMANA8,o.SEMANA9,o.SEMANA10) as SEMANA1,
    COALESCE(o.SEMANA2,o.SEMANA3,o.SEMANA4,o.SEMANA5,o.SEMANA6,o.SEMANA7,o.SEMANA8,o.SEMANA9,o.SEMANA10) as SEMANA2,
    COALESCE(o.SEMANA3,o.SEMANA4,o.SEMANA5,o.SEMANA6,o.SEMANA7,o.SEMANA8,o.SEMANA9,o.SEMANA10) as SEMANA3,
    COALESCE(o.SEMANA4,o.SEMANA5,o.SEMANA6,o.SEMANA7,o.SEMANA8,o.SEMANA9,o.SEMANA10) as SEMANA4,
    COALESCE(o.SEMANA5,o.SEMANA6,o.SEMANA7,o.SEMANA8,o.SEMANA9,o.SEMANA10) as SEMANA5,
    COALESCE(o.SEMANA6,o.SEMANA7,o.SEMANA8,o.SEMANA9,o.SEMANA10) as SEMANA6,
    COALESCE(o.SEMANA7,o.SEMANA8,o.SEMANA9,o.SEMANA10) as SEMANA7,
    COALESCE(o.SEMANA8,o.SEMANA9,o.SEMANA10) as SEMANA8,
    COALESCE(o.SEMANA9,o.SEMANA10) as SEMANA9,
    COALESCE(o.SEMANA10) as SEMANA10
    from (
    
    		SELECT D.CODIGO, 
    		SUM(CASE WHEN  WEEK(FECHAENVIO)=0 THEN D.RONGSHULIANG END ) AS SEMANA1 ,
    		SUM(CASE WHEN  WEEK(FECHAENVIO)=1 THEN D.RONGSHULIANG END ) AS SEMANA2,
    		SUM(CASE WHEN  WEEK(FECHAENVIO)=2 THEN D.RONGSHULIANG END ) AS SEMANA3,
    		SUM(CASE WHEN  WEEK(FECHAENVIO)=3 THEN D.RONGSHULIANG END ) AS SEMANA4,
    		SUM(CASE WHEN  WEEK(FECHAENVIO)=4 THEN D.RONGSHULIANG END ) AS SEMANA5,
    		SUM(CASE WHEN  WEEK(FECHAENVIO)=5 THEN D.RONGSHULIANG END ) AS SEMANA6,
    		SUM(CASE WHEN  WEEK(FECHAENVIO)=6 THEN D.RONGSHULIANG END ) AS SEMANA7,
    		SUM(CASE WHEN  WEEK(FECHAENVIO)=7 THEN D.RONGSHULIANG END ) AS SEMANA8,
    		SUM(CASE WHEN  WEEK(FECHAENVIO)=8 THEN D.RONGSHULIANG END ) AS SEMANA9,
    		SUM(CASE WHEN  WEEK(FECHAENVIO)=9 THEN D.RONGSHULIANG END ) AS SEMANA10
    
    		FROM 
    		   POEE P
    		INNER JOIN 
    		   PEDIDOMOV D ON P.PEDIDOKEY = D.PEDIDOKEY
    		 WHERE
    		   FECHAENVIO >= '20180101' AND FECHAENVIO < '20180201'
    		GROUP BY D.CODIGO, WEEK(FECHAENVIO)
    	) as o
    
    

    si observas el código, se realiza la consulta en una tabla "derivada", o lo que es lo mismo, en un conjunto que se realiza en el FROM entre paréntesis. Mucho cuidado, porque luego la función accede al alias de la tabla, y es case sensitive.

    Tienes que completarlo, ponerle los ifnull y el order by, que me lo he comido.

    Un saludo

    jueves, 21 de junio de 2018 17:45