Foros del Web » Programación para mayores de 30 ;) » Bases de Datos General » Mysql »

[SOLUCIONADO] rango por ventas y por zona

Estas en el tema de rango por ventas y por zona en el foro de Mysql en Foros del Web. hola que tal estimad@s, tengo el siguiente problema y espero que me puedan ayudar de igualmente orientar, les explico tengo una tabla con la siguiente ...
  #1 (permalink)  
Antiguo 09/03/2013, 22:29
Avatar de gerardo_goh  
Fecha de Ingreso: noviembre-2008
Mensajes: 107
Antigüedad: 15 años, 5 meses
Puntos: 1
rango por ventas y por zona

hola que tal estimad@s, tengo el siguiente problema y espero que me puedan ayudar de igualmente orientar, les explico tengo una tabla con la siguiente estructura y datos
Código MySQL:
Ver original
  1. create table tblrango (id_trab           varchar(5)  not null primary key,
  2.                        nombre            varchar(50) not null,
  3.                        zona              varchar(4)  not null,
  4.                        tipo_incidencia   varchar(50) not null,
  5.                        ventas            integer     not null,
  6.                        fec_inicial       date        null,
  7.                        fec_final         date        null,
  8.                        dia_hoy           date        null,
  9.                        origen            varchar(50) not null);
  10.  
  11. insert into tblrango values ('00156','ricardo','0015','trabaja',30,null,null,'2013-02-15','tblrango'),
  12.                             ('04566','gerardo','0015','incapacidad',20,'2013-02-15','2013-02-20','2013-02-15','tblrango'),
  13.                             ('00013','armando','0015','trabaja',25,null,null,'2013-02-15','tblrango'),
  14.                             ('02546','jose','0120','vacaciones',48,'2013-02-10','2013-02-10','2013-02-15','tblrango'),
  15.                             ('01756','francisco','0120','trabaja',30,null,null,'2013-02-15','tblrango'),
  16.                             ('09000','pablo','3000','trabaja',30,null,null,'2013-02-15','tblrango'),
  17.                             ('12300','jonathan','3000','incapacidad',30,'2013-02-05','2013-03-05','2013-02-15','tblrango'),
  18.                             ('12222','ulises','3000','vacaciones',31,'2013-02-12','2013-02-15','2013-02-15','tblrango'),
  19.                             ('05630','julian','3000','trabaja',40,null,null,'2013-02-15','tblrango'),
  20.                             ('15460','pedro','3000','trabaja',41,null,null,'2013-02-15','tblrango');
  21.  
  22.  
  23. +---------+-----------+------+-----------------+--------+-------------+---------
  24. ---+------------+----------+
  25. | id_trab | nombre    | zona | tipo_incidencia | ventas | fec_inicial | fec_fina
  26. l  | dia_hoy    | origen   |
  27. +---------+-----------+------+-----------------+--------+-------------+---------
  28. ---+------------+----------+
  29. | 00013   | armando   | 0015 | trabaja         |     25 | NULL        | NULL
  30.    | 2013-02-15 | tblrango |
  31. | 00156   | ricardo   | 0015 | trabaja         |     30 | NULL        | NULL
  32.    | 2013-02-15 | tblrango |
  33. | 01756   | francisco | 0120 | trabaja         |     30 | NULL        | NULL
  34.    | 2013-02-15 | tblrango |
  35. | 02546   | jose      | 0120 | vacaciones      |     48 | 2013-02-10  | 2013-02-
  36. 10 | 2013-02-15 | tblrango |
  37. | 04566   | gerardo   | 0015 | incapacidad     |     20 | 2013-02-15  | 2013-02-
  38. 20 | 2013-02-15 | tblrango |
  39. | 05630   | julian    | 3000 | trabaja         |     40 | NULL        | NULL
  40.    | 2013-02-15 | tblrango |
  41. | 09000   | pablo     | 3000 | trabaja         |     30 | NULL        | NULL
  42.    | 2013-02-15 | tblrango |
  43. | 12222   | ulises    | 3000 | vacaciones      |     31 | 2013-02-12  | 2013-02-
  44. 15 | 2013-02-15 | tblrango |
  45. | 12300   | jonathan  | 3000 | incapacidad     |     30 | 2013-02-05  | 2013-03-
  46. 05 | 2013-02-15 | tblrango |
  47. | 15460   | pedro     | 3000 | trabaja         |     41 | NULL        | NULL
  48.    | 2013-02-15 | tblrango |
  49. +---------+-----------+------+-----------------+--------+-------------+---------
  50. ---+------------+----------+
  51. 10 rows in set (0.00 sec)

necesito obtener el siguiente resultado:

http://www.freeimagehosting.net/9h3yv

Anexo el link por que no se como subir imagenes

la idea es que me diga el rango por grupo por la cantidad de ventas generadas por el trabajador ademas de las columnas cant_dias_no_lab es el resultado de total de dias de la incidencia, y la columna tot_dias_hoy es la cantidad de dias que lleva de incidencia hasta la fecha de la columna dia_hoy, espero que me puedan ayudar, muchas gracias
  #2 (permalink)  
Antiguo 11/03/2013, 08:55
Colaborador
 
Fecha de Ingreso: enero-2007
Ubicación: México
Mensajes: 2.097
Antigüedad: 17 años, 3 meses
Puntos: 447
Respuesta: rango por ventas y por zona

Hola gerardo_goh:

Te recuerdo que aquí te podemos ayudar a resolver tus dudas, pero que de ninguna manera te podemos hacer el trabajo... En realidad en tu post no expresas qué problemas tienes o qué dudas tienes, por lo tanto es algo complicado dar una respuesta puntual. ¿Qué intentaste hacer? porque supongo que intentaste hacer algo verdad?, coloca las consultas que intentaste hacer, no importa que sean erróneas, a partir de eso podemos ayudarte a afinarla o indicarte alguna otra alternativa. Por lo pronto hagamos algunas acotaciones:

1. Para el rango: en realidad no nos explicas cómo es que asignas cada valor (1-4). dices que dependen de la cantidad de ventas generadas, pero cómo son estos rangos??? porque por ejemplo

Código:
Ricardo tiene ventas = 30 y un rango = 1
Pablo   tiene ventas = 30 y un rango = 4 ??????????
Para hacer esta clasificación puedes hacerlo mediante un CASE-WHEN o mediante un IF.

http://dev.mysql.com/doc/refman/5.0/...functions.html

2. Para la cantidad de días. Puedes hacerlo con la función DATEDIFF:

Cita:
DATEDIFF(expr,expr2)

DATEDIFF() retorna el número de días entre la fecha inicial expr y la fecha final expr2. expr y expr2 son expresiones de fecha o de fecha y hora. Sólo las partes de fecha de los valores se usan en los cálculos.
http://dev.mysql.com/doc/refman/5.0/...functions.html

Haz la prueba, intenta sacar la consulta por tu propia cuenta y si continuas con dudas publica lo que hiciste y con gusto te ayudamos.

Saludos
Leo.
  #3 (permalink)  
Antiguo 11/03/2013, 22:28
Avatar de gerardo_goh  
Fecha de Ingreso: noviembre-2008
Mensajes: 107
Antigüedad: 15 años, 5 meses
Puntos: 1
Respuesta: rango por ventas y por zona

Hola que tal, creo que expuse el tema mal, lo que necesito es obtener el ranking de los mejores vendedores, pongo un ejemplo de excel:

http://jldexcelsp.blogspot.mx/2011/0...or-grupos.html

Esto es lo que llevo creado.

Código MySQL:
Ver original
  1. -- ============ PASO 1=============
  2. -- Crear una tabla temporal
  3. create table tblvta_alta as
  4.  
  5. select concat(a.id_trab,'-',a.nombre,'-',a.zona,'-',a.ventas)as key_2,a.id_trab,a.nombre,a.zona,a.tipo_incidencia,a.ventas,
  6.       ifnull(a.fec_inicial,'') fec_inicio,
  7.       ifnull(a.fec_final,'')fec_fin,
  8.       b.lugar,
  9.       if(a.fec_inicial,datediff(a.fec_final,a.fec_inicial)+1,' ')cant_dia_no_lab,
  10.       if(a.fec_final>a.dia_hoy,datediff(a.dia_hoy,a.fec_inicial)+1,' ')tot_dias_hoy,
  11.       a.dia_hoy
  12. from tblrango a
  13.  
  14.  
  15. (select b.zona,max(b.ventas) maxventas,(1) lugar
  16. from tblrango b
  17. group by b.zona
  18. order by b.zona asc) b
  19.  
  20. on  a.zona = b.zona
  21. and a.ventas=b.maxventas;
  22.  
  23. select * from tblvta_alta;
  24.  
  25.  
  26. -- ============ PASO 2 ==================
  27. -- Para determinar los días no laborados hasta el 2013-02-15 y el total de dias de incidencia diferente a trabaja
  28. create table tblfechas as
  29. select concat(a.id_trab,'-',a.nombre,'-',a.zona,'-',a.ventas)as key_1,a.zona,a.id_trab,a.nombre,a.tipo_incidencia,a.ventas,
  30.       ifnull(fec_inicial,'')as fecha_ini,
  31.       ifnull(fec_final,'')as fecha_fin,
  32.       if(a.fec_inicial,datediff(a.fec_final,a.fec_inicial)+1,' ')cant_dia_no_lab,
  33.       if(a.fec_final>a.dia_hoy,datediff(a.dia_hoy,a.fec_inicial)+1,' ')tot_dias_hoy
  34.  
  35.  
  36. from tblrango a;
  37.  
  38. select * from tblfechas;
  39.  
  40.  
  41. -- ============ Paso 3 ==================
  42. -- Unir tablas del paso 1 con la del paso 2
  43.  
  44. select a.id_trab,a.nombre,a.zona,a.tipo_incidencia,a.ventas,
  45. ifnull(b.lugar,'')lugar,a.fecha_ini,a.fecha_fin,a.cant_dia_no_lab,a.tot_dias_hoy,
  46. if(fecha_ini='','trabaja','descanso')ruta from tblfechas a
  47. left outer join tblvta_alta b
  48. on a.key_1=b.key_2
  49. order by a.zona asc,a.ventas desc;
  50.  
  51. -- el dia_hoy es: 2013-02-15 sobre esa fecha fueron los calculos de las columnas cant_dia_no_lab  y tot_dias_hoy
  52.  
  53. +---------+-----------+------+-----------------+--------+-------+------------+------------+-----------------+--------------+----------+
  54. | id_trab | nombre    | zona | tipo_incidencia | ventas | lugar | fecha_ini  | fecha_fin  | cant_dia_no_lab | tot_dias_hoy | ruta     |
  55. +---------+-----------+------+-----------------+--------+-------+------------+------------+-----------------+--------------+----------+
  56. | 00156   | ricardo   | 0015 | trabaja         |     30 | 1     |            |            |                 |              | trabaja  |
  57. | 00013   | armando   | 0015 | trabaja         |     25 |       |            |            |                 |              | trabaja  |
  58. | 04566   | gerardo   | 0015 | incapacidad     |     20 |       | 2013-02-15 | 2013-02-20 | 6               | 1            | descanso |
  59. | 02546   | jose      | 0120 | vacaciones      |     48 | 1     | 2013-02-10 | 2013-02-10 | 1               |              | descanso |
  60. | 01756   | francisco | 0120 | trabaja         |     30 |       |            |            |                 |              | trabaja  |
  61. | 15460   | pedro     | 3000 | trabaja         |     41 | 1     |            |            |                 |              | trabaja  |
  62. | 05630   | julian    | 3000 | trabaja         |     40 |       |            |            |                 |              | trabaja  |
  63. | 12222   | ulises    | 3000 | vacaciones      |     31 |       | 2013-02-12 | 2013-02-15 | 4               |              | descanso |
  64. | 09000   | pablo     | 3000 | trabaja         |     30 |       |            |            |                 |              | trabaja  |
  65. | 12300   | jonathan  | 3000 | incapacidad     |     30 |       | 2013-02-05 | 2013-03-05 | 29              | 11           | descanso |
  66. +---------+-----------+------+-----------------+--------+-------+------------+------------+-----------------+--------------+----------+
  67. 10 rows in set (0.00 sec)

Hasta el momento esto es lo que tengo me hace falta obtener los demas ranking de los vendedores por zona de acuerdo a las ventas generadas por cada zona.

Espero que me puedan ayudar.

Última edición por gerardo_goh; 12/03/2013 a las 08:11
  #4 (permalink)  
Antiguo 12/03/2013, 10:06
Colaborador
 
Fecha de Ingreso: enero-2007
Ubicación: México
Mensajes: 2.097
Antigüedad: 17 años, 3 meses
Puntos: 447
Respuesta: rango por ventas y por zona

Hola de nuevo gerardo_goh:

Lamentablemente MySQL no cuenta con funciones RANK o ROW_COUNT que poseen otros motores como ORACLE o SQL Server, y que son las indicadas para hacer lo que necesitas, sin embargo hay varias técnicas que puedes utilizar para simular estas funciones. Checa esta liga:

RANK:
http://www.artfulsoftware.com/infotr...tip.php?id=460

ROW_NUMBER:
http://www.artfulsoftware.com/infotr...ip.php?id=1098


Como podrás observar la consulta no es tan trivial, pero en realidad no es tan complicada llevarla a la práctica. Me voy a enfocar sólo en lo que te falta que es el RANK de ventas... sería más o menos así, basándonos en los siguientes datos:

Código MySQL:
Ver original
  1. mysql> SELECT id_trab, nombre, zona, ventas FROM tblrango;
  2. +---------+-----------+------+--------+
  3. | id_trab | nombre    | zona | ventas |
  4. +---------+-----------+------+--------+
  5. | 00013   | armando   | 0015 |     25 |
  6. | 00156   | ricardo   | 0015 |     30 |
  7. | 04566   | gerardo   | 0015 |     20 |
  8. | 01756   | francisco | 0120 |     30 |
  9. | 02546   | jose      | 0120 |     48 |
  10. | 05630   | julian    | 3000 |     40 |
  11. | 09000   | pablo     | 3000 |     30 |
  12. | 12222   | ulises    | 3000 |     31 |
  13. | 12300   | jonathan  | 3000 |     30 |
  14. | 15460   | pedro     | 3000 |     41 |
  15. +---------+-----------+------+--------+
  16. 10 rows in set (0.00 sec)


La idea de la función RANK es hacer una subconsulta para cada registro donde cuentes cuantos registros existen con ventas mayores o iguales a la que se está analizando. Sería más o menos así:

Código MySQL:
Ver original
  1. mysql> SELECT v1.id_trab, v1.nombre, v1.zona,
  2.     -> v1.ventas, COUNT(v2.ventas) AS Rank
  3.     -> FROM tblrango v1
  4.     -> INNER JOIN tblrango v2 ON
  5.     ->   v1.zona = v2.zona AND
  6.     ->   v1.ventas < v2.ventas OR
  7.     ->   (v1.ventas = v2.ventas AND v1.zona = v2.zona AND
  8.     ->    v1.id_trab = v2.id_trab)
  9.     -> GROUP BY v1.id_trab, v1.zona, v1.ventas
  10.     -> ORDER BY v1.zona, v1.ventas DESC, v1.id_trab;
  11. +---------+-----------+------+--------+------+
  12. | id_trab | nombre    | zona | ventas | Rank |
  13. +---------+-----------+------+--------+------+
  14. | 00156   | ricardo   | 0015 |     30 |    1 |
  15. | 00013   | armando   | 0015 |     25 |    2 |
  16. | 04566   | gerardo   | 0015 |     20 |    3 |
  17. | 02546   | jose      | 0120 |     48 |    1 |
  18. | 01756   | francisco | 0120 |     30 |    2 |
  19. | 15460   | pedro     | 3000 |     41 |    1 |
  20. | 05630   | julian    | 3000 |     40 |    2 |
  21. | 12222   | ulises    | 3000 |     31 |    3 |
  22. | 09000   | pablo     | 3000 |     30 |    4 |
  23. | 12300   | jonathan  | 3000 |     30 |    4 |
  24. +---------+-----------+------+--------+------+
  25. 10 rows in set (0.00 sec)

También podrías hacerlo con la función ROW_NUMBER, la idea aquí es en primer lugar ordenar los registros por zona y por ventas, utilizar una variable temporal para almacenar la zona y un contador para la posición. Mientras se analice la misma zona, se va incrementando el contador para poner la posición, cuando se detecta un cambio de zona entonces se inicializa el contador a 1... sería más o menos así:

Primero inicializamos las variables temprales que vamos a utilizar:

Código MySQL:
Ver original
  1. mysql> SET @zonaPrev=0, @ventasPrev=0, @ordPrev=0;
  2. Query OK, 0 rows affected (0.00 sec)
  3.  
  4. mysql> SELECT id_trab, nombre, zona, ventas, row_number
  5.     -> FROM (
  6.     ->   SELECT
  7.     ->     ventas, id_trab, nombre,
  8.     ->     @ordPrev := IF(@zonaPrev = zona,
  9.     ->                    IF(ventas != @ventasPrev, @ordPrev+1, @ordPrev),
  10.     ->                    1) AS row_number,
  11.     ->     @zonaPrev := zona AS zona,
  12.     ->     @ventasPrev := ventas AS ventasPrev
  13.     ->   FROM tblrango
  14.     ->   ORDER BY zona, ventas DESC, id_trab, nombre
  15.     -> ) tmp;
  16. +---------+-----------+------+--------+------------+
  17. | id_trab | nombre    | zona | ventas | row_number |
  18. +---------+-----------+------+--------+------------+
  19. | 00156   | ricardo   | 0015 |     30 |          1 |
  20. | 00013   | armando   | 0015 |     25 |          2 |
  21. | 04566   | gerardo   | 0015 |     20 |          3 |
  22. | 02546   | jose      | 0120 |     48 |          1 |
  23. | 01756   | francisco | 0120 |     30 |          2 |
  24. | 15460   | pedro     | 3000 |     41 |          1 |
  25. | 05630   | julian    | 3000 |     40 |          2 |
  26. | 12222   | ulises    | 3000 |     31 |          3 |
  27. | 09000   | pablo     | 3000 |     30 |          4 |
  28. | 12300   | jonathan  | 3000 |     30 |          4 |
  29. +---------+-----------+------+--------+------------+
  30. 10 rows in set (0.00 sec)

Si comparas este ejercicio con el que te pongo en la liga, observarás que yo utilizo una segunda variable ventasTemp, esto es para evitar que cuando se trate de ventas iguales te ponga un orden distinto, como en los últimos dos registros, si lo hago como aparece en el ejemplo sería así:

Código MySQL:
Ver original
  1. mysql> SET @zonaPrev=0, @ordPrev=0;
  2. Query OK, 0 rows affected (0.00 sec)
  3.  
  4. mysql> SELECT id_trab, nombre, zona, ventas, row_number
  5.     -> FROM (
  6.     ->   SELECT
  7.     ->     ventas, id_trab, nombre,
  8.     ->     @ordPrev := IF(@zonaPrev = zona, @ordPrev+1, 1) AS row_number,
  9.     ->     @zonaPrev := zona AS zona
  10.     ->   FROM tblrango
  11.     ->   ORDER BY zona, ventas DESC, id_trab, nombre
  12.     -> ) tmp;
  13. +---------+-----------+------+--------+------------+
  14. | id_trab | nombre    | zona | ventas | row_number |
  15. +---------+-----------+------+--------+------------+
  16. | 00156   | ricardo   | 0015 |     30 |          1 |
  17. | 00013   | armando   | 0015 |     25 |          2 |
  18. | 04566   | gerardo   | 0015 |     20 |          3 |
  19. | 02546   | jose      | 0120 |     48 |          1 |
  20. | 01756   | francisco | 0120 |     30 |          2 |
  21. | 15460   | pedro     | 3000 |     41 |          1 |
  22. | 05630   | julian    | 3000 |     40 |          2 |
  23. | 12222   | ulises    | 3000 |     31 |          3 |
  24. | 09000   | pablo     | 3000 |     30 |          4 |
  25. | 12300   | jonathan  | 3000 |     30 |          5 |
  26. +---------+-----------+------+--------+------------+
  27. 10 rows in set (0.00 sec)

Observa que en los últimos dos registros les asigna rangos diferentes (4, 5).

Trata de analizar las consultas pero sobre todo trata de entenderlas, practica algunas otras consultas, estoy seguro que este tipo de consultas te servirán en un futuro.

Saludos.
  #5 (permalink)  
Antiguo 12/03/2013, 20:53
Avatar de gerardo_goh  
Fecha de Ingreso: noviembre-2008
Mensajes: 107
Antigüedad: 15 años, 5 meses
Puntos: 1
De acuerdo Respuesta: rango por ventas y por zona

Muchas gracias, es lo que necesitaba, pongo el tema como solucionado, una pregunta como pongo en mis preguntas imagenes como otros temas: ejemplo:

http://www.forosdelweb.com/f86/mostr...s-alta-949576/

o

http://www.forosdelweb.com/f86/agrup...fechas-947318/

de nuevo muchas gracias por todo, me haz ayudado mucho.
  #6 (permalink)  
Antiguo 13/03/2013, 01:47
sjj
 
Fecha de Ingreso: octubre-2008
Mensajes: 213
Antigüedad: 15 años, 5 meses
Puntos: 12
Respuesta: rango por ventas y por zona

Las imágenes que quieras postear deben estar en alguna URL. Haces click en la opción "Insertar Imagen"--> y ahí introduces la URL de la imagen que deseas incluir.

Etiquetas: insert, rango, ranking, tabla, ventas
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 22:06.