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

Problema Real

Estas en el tema de Problema Real en el foro de Mysql en Foros del Web. hola! amigos del foro tengo un pequeño problemita tengo una tabla que tiene informacion de trabajadores de una empresa codigo, nombre, sueldo, ciudad, jefe el ...
  #1 (permalink)  
Antiguo 26/08/2009, 07:15
 
Fecha de Ingreso: mayo-2009
Mensajes: 76
Antigüedad: 15 años, 5 meses
Puntos: 1
Problema Real

hola! amigos del foro


tengo un pequeño problemita


tengo una tabla que tiene informacion de trabajadores de una empresa

codigo, nombre, sueldo, ciudad, jefe



el problema surge cuando tengo que hacer una consulta. el campo jefe refencio el numero de condigo de la persona que es el jefe.

por ejemplo


codigo - nombre- suledo - ciudad - jefe

80751, kaydu, 4970000, bogota, null

10101 , noora, 6000, bogta, 80751

10829, parra, 460 , cali, 80751

52917 , mayra , 5000 , baranquilla, 10829



1. tengo que mostrar un listado de todos los que sean jefes


2. listar empleados que ganan mas que el jefe


3. listar datos de los jefes que tienen mas de un subalterno.


Gracias!
  #2 (permalink)  
Antiguo 26/08/2009, 07:43
Colaborador
 
Fecha de Ingreso: marzo-2008
Ubicación: Cáceres
Mensajes: 3.735
Antigüedad: 16 años, 7 meses
Puntos: 300
Respuesta: Problema Real

Parece que os han puesto el mismo ejercicio a varios. Mira este enlace:
http://www.forosdelweb.com/f86/pregu...nsulta-730346/

Te añado aquí el que te falta:
3) los que son jefes
SELECT Nombre from tabla WHERE Jefe IS NULL

y un consejo: a hacer consultas aprenderás mejor haciendo consultas y, sobre todo, equivocándote al hacerlas. Haz pruebas con las que os he puesto y si no entiendes algo pregunta el porqué.
  #3 (permalink)  
Antiguo 26/08/2009, 09:58
Avatar de huesos52
Colaborador
 
Fecha de Ingreso: febrero-2009
Ubicación: Manizales - Colombia
Mensajes: 5.980
Antigüedad: 15 años, 9 meses
Puntos: 360
Respuesta: Problema Real

Añado una pequeña mejora a la ultima solución propuesta por jurena.

Cita:
Te añado aquí el que te falta:
3) los que son jefes
SELECT Nombre from tabla WHERE Jefe IS NULL
Esto solo muestra el maximo jefe. Pero para el caso del ejemplo, pueden haber jefes que tienen jefes también.

Código sql:
Ver original
  1. SELECT t1.* FROM tabla t1
  2. INNER JOIN
  3. (SELECT Jefe FROM tabla GROUP BY Jefe HAVING COUNT(*) > 0) t2
  4. ON t1.doc=t2.jefe;

saludos
__________________
Without data, You are another person with an opinion.
W. Edwads Deming
  #4 (permalink)  
Antiguo 26/08/2009, 11:44
Colaborador
 
Fecha de Ingreso: marzo-2008
Ubicación: Cáceres
Mensajes: 3.735
Antigüedad: 16 años, 7 meses
Puntos: 300
Respuesta: Problema Real

Lleva razón huesos52.
No me había percatado de ese detalle.
Saludos a ambos.

Última edición por jurena; 26/08/2009 a las 11:58
  #5 (permalink)  
Antiguo 26/08/2009, 12:16
Colaborador
 
Fecha de Ingreso: marzo-2008
Ubicación: Cáceres
Mensajes: 3.735
Antigüedad: 16 años, 7 meses
Puntos: 300
Respuesta: Problema Real

Respondo sin editar para evitar confusiones.
Creo que para sacar los jefes, esto podría valer:
Código sql:
Ver original
  1. SELECT doc, Nombre, Jefe FROM tabla WHERE Doc IN(SELECT DISTINCT Jefe FROM tabla WHERE jefe IS NOT NULL) UNION SELECT doc, Nombre, Jefe FROM tabla WHERE jefe IS NULL ORDER BY Jefe
La razón es que, como dice huesos52, se hace necesario encontrar el jefe máximo y los que son jefes de otro.
Quizás haya otra mejor, pero sólo se me ocurre esta.
  #6 (permalink)  
Antiguo 26/08/2009, 12:27
Avatar de huesos52
Colaborador
 
Fecha de Ingreso: febrero-2009
Ubicación: Manizales - Colombia
Mensajes: 5.980
Antigüedad: 15 años, 9 meses
Puntos: 360
Respuesta: Problema Real

Es una opción muy factible jurena. Pero no crees que requiera de demasiados procesos para llegar a un mismo resultado? La que pongo en el post, realiza la misma tarea.

haciendo un explain de las consultas, creo que puede ser mas optima la priimera opción. O que opinas?
Código sql:
Ver original
  1. mysql> EXPLAIN SELECT t1.doc,t1.nombre,t1.jefe FROM empleados t1 INNER JOIN (SELECT Jefe FROM empleados GROUP BY Jefe HAVING COUNT(*) > 0) t2 ON t1.doc=t2.jefe;
  2. +----+-------------+------------+--------+---------------+---------+---------+---------+------+-------------+
  3. | id | select_type | TABLE      | TYPE   | possible_keys | KEY     | key_len | REF     | ROWS | Extra       |
  4. +----+-------------+------------+--------+---------------+---------+---------+---------+------+-------------+
  5. |  1 | PRIMARY     | <derived2> | ALL    | NULL          | NULL    | NULL    | NULL    |    3 |             |
  6. |  1 | PRIMARY     | t1         | eq_ref | PRIMARY       | PRIMARY | 4       | t2.Jefe |    1 |             |
  7. |  2 | DERIVED     | empleados  | INDEX  | NULL          | jefe    | 5       | NULL    |    5 | USING INDEX |
  8. +----+-------------+------------+--------+---------------+---------+---------+---------+------+-------------+
  9. 3 ROWS IN SET (0.00 sec)
  10.  
  11. mysql> EXPLAIN SELECT doc, Nombre, Jefe FROM empleados WHERE
  12. Doc IN(SELECT DISTINCT Jefe FROM empleados WHERE jefe IS NOT NULL)
  13. UNION SELECT doc, Nombre, Jefe FROM empleados WHERE jefe IS NULL ORDER BY Jefe;
  14. +----+--------------------+------------+----------------+---------------+------+---------+-------+------+--------------------------+
  15. | id | select_type        | TABLE      | TYPE           | possible_keys | KEY  | key_len | REF   | ROWS | Extra                    |
  16. +----+--------------------+------------+----------------+---------------+------+---------+-------+------+--------------------------+
  17. |  1 | PRIMARY            | empleados  | ALL            | NULL          | NULL | NULL    | NULL  |    5 | USING WHERE              |
  18. |  2 | DEPENDENT SUBQUERY | empleados  | index_subquery | jefe          | jefe | 5       | func  |    2 | USING INDEX; USING WHERE |
  19. |  3 | UNION              | empleados  | REF            | jefe          | jefe | 5       | const |    1 | USING WHERE              |
  20. | NULL | UNION RESULT       | <union1,3> | ALL            | NULL          | NULL | NULL    | NULL  | NULL | USING filesort           |
  21. +----+--------------------+------------+----------------+---------------+------+---------+-------+------+--------------------------+
  22. 4 ROWS IN SET (0.00 sec)
  23.  
  24. mysql>

lastimosamente no cuento con una tabla grande de este tipo para hacer las respectivas pruebas de rendimiento
__________________
Without data, You are another person with an opinion.
W. Edwads Deming
  #7 (permalink)  
Antiguo 26/08/2009, 13:17
Colaborador
 
Fecha de Ingreso: marzo-2008
Ubicación: Cáceres
Mensajes: 3.735
Antigüedad: 16 años, 7 meses
Puntos: 300
Respuesta: Problema Real

Totalmente de acuerdo contigo, amigo huesos52,
al parecer, al copiar la propuesta arrastré un algún dato mal que me hizo pensar que no traía todos los datos (cosas de copiar directamente en lugar de usar el botón de copiar o ver original). Me quedo con tu propuesta, porque, creo, que será siempre más eficiente.

Saludos
  #8 (permalink)  
Antiguo 26/08/2009, 14:31
Colaborador
 
Fecha de Ingreso: marzo-2008
Ubicación: Cáceres
Mensajes: 3.735
Antigüedad: 16 años, 7 meses
Puntos: 300
Respuesta: Problema Real

Una duda para vosotros los técnicos, huesos52; tengo que plantearla:
¿qué pensáis de una consulta como esta para el caso?

Código sql:
Ver original
  1. SELECT Doc, Nombre FROM tabla WHERE Doc IN (SELECT DISTINCT Jefe FROM tabla)

Tal vez sea menos eficiente porque quizás no recurra a los índices, pero...
  #9 (permalink)  
Antiguo 26/08/2009, 15:13
Avatar de huesos52
Colaborador
 
Fecha de Ingreso: febrero-2009
Ubicación: Manizales - Colombia
Mensajes: 5.980
Antigüedad: 15 años, 9 meses
Puntos: 360
Respuesta: Problema Real

Efectivamente es mucho mas simple que la que planteas primero.

Mi experiencia en eficiencia de consultas sql (Lastimosamente no con MySQL) me ha dicho que el uso de subconsultas utilizadas en los condicionales, puede ser ineficiente para una gran cantidad de registros.
Particularmente en postgres, La comparación entre el uso de consultas con subqueries en la clausula in y el manejo de anidaciones de las tablas, tiene tiempos de respuesta con muchísima diferencia. (Mas de 60 segundos)

Desde aquel día, solo hago uso de las subconsultas en los condicionales cuando estoy seguro que la cantidad de registros no sea muy grande (Por su facilidad).

Una explicación analítica que le doy a esta situación (Mas no una explicación teóricamente comprobada) es la necesidad de ejecutar todas las subconsultas con un orden prioritario para después aplicar dichos resultados a la consulta principal. De la otra forma, considero se hace una especie de filtrado inicial que permite establecer los registros a mostrar sin la necesidad de ejecutar la totalidad de los registros de las tablas involucradas en la consulta.

Sin embargo, esperemos la opinión de personas con mas experiencia que nos den su punto de vista con respecto a este tema.

De este tipo de mensajes es que cada día nos enriquecemos mas.

saludos jurena y richarparrao que no se ha pronunciado.
__________________
Without data, You are another person with an opinion.
W. Edwads Deming

Última edición por huesos52; 26/08/2009 a las 15:23
  #10 (permalink)  
Antiguo 27/08/2009, 01:24
Colaborador
 
Fecha de Ingreso: marzo-2008
Ubicación: Cáceres
Mensajes: 3.735
Antigüedad: 16 años, 7 meses
Puntos: 300
Respuesta: Problema Real

huesos52 y demás amigos,
tu explicación es convincente, al menos para mí. Pero sigo con el hilo un poco más. Si te soy sincero, a mí lo que me sabe raro de tu consulta es el having COUNT(*) > 0, cuya función es, creo, poder evitar el NULL y hacer el INNER JOIN, lo que permite una consulta más rápida. Y aquí va mi otra cuestión: ¿una consulta con WHERE sería más o menos eficiente que el uso de HAVING, teniendo en cuenta que el distinct es como el group by...? Lo explicaré con el ejemplo de la que yo tengo en mente:
Código sql:
Ver original
  1. SELECT Doc, Nombre FROM tabla INNER JOIN (SELECT DISTINCT Jefe
  2.  FROM tabla WHERE Jefe IS NOT NULL)T1 ON tabla.Doc = T1.Jefe
Una vez más, gracias.
  #11 (permalink)  
Antiguo 27/08/2009, 07:06
Avatar de huesos52
Colaborador
 
Fecha de Ingreso: febrero-2009
Ubicación: Manizales - Colombia
Mensajes: 5.980
Antigüedad: 15 años, 9 meses
Puntos: 360
Respuesta: Problema Real

Pues jurena... me gusta muchísimo mas .

El having, se me pasó por alto, ya que pensé que el campo a comparar era doc y no jefe. Como el campo a comparar es jefe, los resultados encontrados, serán siempre jefes independiente del nivel que manejen. (Incluyendo los NULL)

Código sql:
Ver original
  1. SELECT Doc, Nombre FROM tabla INNER JOIN (SELECT DISTINCT Jefe
  2.  FROM tabla)T1 ON tabla.Doc = T1.Jefe

o

Código sql:
Ver original
  1. SELECT Doc, Nombre FROM tabla INNER JOIN (SELECT Jefe
  2.  FROM tabla GROUP BY jefe)T1 ON tabla.Doc = T1.Jefe

que son equivalentes.

saludos y gracias a ti amigo.
__________________
Without data, You are another person with an opinion.
W. Edwads Deming

Última edición por huesos52; 27/08/2009 a las 07:35
  #12 (permalink)  
Antiguo 27/08/2009, 09:52
Colaborador
 
Fecha de Ingreso: marzo-2008
Ubicación: Cáceres
Mensajes: 3.735
Antigüedad: 16 años, 7 meses
Puntos: 300
Respuesta: Problema Real

Yo me quedo con esta:
Código sql:
Ver original
  1. SELECT Doc, Nombre FROM tabla INNER JOIN (SELECT Jefe
  2.  FROM tabla GROUP BY Jefe)T1 ON tabla.Doc = T1.Jefe
Porque esta otra da problemas, al menos al lanzar la consulta desde PHPMyAdmin
SELECT Doc, Nombre FROM tabla INNER JOIN (SELECT DISTINCT Jefe
FROM tabla)T1 ON tabla.Doc = T1.Jefe
Parece que no son del todo equivalentes. Para hacerlo con distinct, al menos en PHPMyAdmin, tienes que sacar los NULL, como en la propuesta que hice:
SELECT Doc, Nombre FROM tabla INNER JOIN (SELECT DISTINCT Jefe
FROM tabla WHERE Jefe IS NOT NULL)T1 ON tabla.Doc = T1.Jefe
y aunque el NULL puede sacarse, porque el número Cod saldra como jefe de otro, sin embargo es mucho mejor la primera de las dos últimas que propuso huesos52.

Última edición por jurena; 27/08/2009 a las 10:03
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 13:46.