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

problema con recuento de registros

Estas en el tema de problema con recuento de registros en el foro de Mysql en Foros del Web. Hola amig@s. Mi duda surge a la hora de contar los registros de una tabla agrupados por 2 campos y coincidentes con otras 2 tablas ...
  #1 (permalink)  
Antiguo 13/02/2011, 09:20
Avatar de aniMAYtions  
Fecha de Ingreso: diciembre-2007
Ubicación: Granada
Mensajes: 519
Antigüedad: 16 años, 11 meses
Puntos: 2
problema con recuento de registros

Hola amig@s.
Mi duda surge a la hora de contar los registros de una tabla agrupados por 2 campos y coincidentes con otras 2 tablas externas, contando también los que no tienen registros como 0.
Me explico mejor. Tengo una tabla 'servicios' que tiene, entre otre otros, 3 campos clave para mi consulta. Estos son empresa, caracter y tipo.
Resulta que yo soy el coordinador regional de esta empresa y en mi comunidad tengo varias empresas a mi cargo. Hay varios tipos de servicios que ofrecemos y estos servicios pueden ser de 2 caracteres, públicos o privados.
Como ya os he dicho, yo llevo varias empresas, pero me encuentro situado en una(tecnico, id_empresa), aunque esta empresa pertenece a la comunidad autónoma que abarca todas.
Ahora, debería saber el número de servicios registrados de cada tipo y caracter sólo de las empresas de mi ámbito.
Algo como ésto:
Código SQL:
Ver original
  1. tipos | Caracter | COUNT(*)
  2. ------------------------------------------
  3. tipo1 | Público    |
  4. -------------------------------------------
  5. tipo1 | Privado   |
  6. ------------------------------------------
  7. tipo2 | Público    |
  8. -------------------------------------------
  9. tipo2 | Privado   |
  10. ---------------------------------------------
  11. tipo3 | Público    |
  12. -----------------------------------------------
  13. tipo3 | Privado   |

Ahí deben aparecer todos los tipos de la tabla tipos con los 2 caracteres, hayan o no servicios relacionados.

My consulta en estos momentos es
Código SQL:
Ver original
  1. SELECT nombre_tipo, nombre_caracter, COUNT(*) FROM servicios s(v), tipos t(tv), caracte c(cv)  WHERE s.id_tipo = t.id_tipo AND s.id_caracter = c.id_caracter AND s.id_empresa IN(SELECT e.id_empresa FROM empresas e WHERE id_comunidad IN(SELECT id_comunidad FROM empresas e, tecnicos t WHERE e.id_empresa = t.id_empresa AND id_tecnico = '$id_tec')) AND s.id_caracter IS NOT NULL
  2. GROUP BY   s.id_tipo, s.id_caracter

Esto me arroja sólo el resultado de los tipos de los que hay servicios realizados, pero los otros nada. Y lo que me gustaría sería listar todos los tipos, los caracteres por tipo y el número de servicios aunque sea 0.

Me he explicado bien? Espero no haberos aburrido.
Un saludo y gracias!!
  #2 (permalink)  
Antiguo 14/02/2011, 01:44
Avatar de Heimish2000  
Fecha de Ingreso: enero-2011
Ubicación: Madrid
Mensajes: 844
Antigüedad: 13 años, 10 meses
Puntos: 89
Respuesta: problema con recuento de registros

Con un left join es muy facil.

En cualquier caso, mi recomendacion es cuando unas tablas, utilizar sentencias JOIN en vez de unirlas directamente

Código SQL:
Ver original
  1. SELECT nombre_tipo, nombre_caracter, COUNT(*)
  2. FROM servicios s(v)
  3. LEFT JOIN tipos t(tv) ON
  4. s.id_tipo = t.id_tipo
  5. LEFT JOIN caracte c(cv)  ON
  6. s.id_caracter = c.id_caracter
  7. WHERE  s.id_empresa IN (SELECT e.id_empresa
  8. FROM empresas e
  9. WHERE id_comunidad IN
  10. (SELECT id_comunidad
  11. FROM empresas e, tecnicos t
  12. WHERE e.id_empresa = t.id_empresa
  13. AND id_tecnico = '$id_tec'))
  14. AND s.id_caracter IS NOT NULL
  15. GROUP BY s.id_tipo, s.id_caracter
  #3 (permalink)  
Antiguo 14/02/2011, 04:29
Avatar de aniMAYtions  
Fecha de Ingreso: diciembre-2007
Ubicación: Granada
Mensajes: 519
Antigüedad: 16 años, 11 meses
Puntos: 2
Respuesta: problema con recuento de registros

Muchas gracias por tu respuesta Heimish2000, pero resulta que me han exigido mostrar los datos de otra forma y eso no voy a poder conseguirlo con una sola consulta. El nuevo requerimiento es este:
Código SQL:
Ver original
  1. tipos | Público   | Privado
  2.       ------------------------------------------
  3.       tipo1 | COUNT(*)| COUNT(*)
  4.       -------------------------------------------
  5.       tipo2 | COUNT(*)| COUNT(*)
  6.       ------------------------------------------
  7.       tipo3 | COUNT(*)| COUNT(*)
  8.       -------------------------------------------
  9.       tipo4 | COUNT(*)| COUNT(*)
  10.       ---------------------------------------------
  11.       tipo5 | COUNT(*)| COUNT(*)
  12.       -----------------------------------------------
  13.       tipo6 | COUNT(*)| COUNT(*)

Así que lo que he hecho es, en primer lugar, listar los tipos y mientras los voy mostrando con un while en php coloco en el primer td el tipo, para el segundo td hago otra consulta y cuento el número de servicios de ese tipo que sean públicos y para el tercer td repito la consulta anterior cambiando el id_caracter por 2.
Es la única solución que se me ocurre por el momento.
Pero ya por tener algún conocimiento más sobre sql(olvidé el uso de left y right join), habría alguna consulta para obtener los resultados en este orden?

Saludos y gracias de nuevo.
  #4 (permalink)  
Antiguo 14/02/2011, 05:30
Avatar de Heimish2000  
Fecha de Ingreso: enero-2011
Ubicación: Madrid
Mensajes: 844
Antigüedad: 13 años, 10 meses
Puntos: 89
Respuesta: problema con recuento de registros

Seria algo así (yo te doy la idea, la solución exacta tienes que sacarla tu)

Código SQL:
Ver original
  1. SELECT TIPO, SUM(PUB), SUM(PRI)
  2. FROM
  3. (
  4. SELECT TIPO, CASE WHEN CARACTER = 'Público' THEN '1' ELSE '0' END AS PUB,
  5. CASE WHEN CARACTER = 'Privado' THEN '1' ELSE '0' END AS PRI
  6. FROM TIPOS
  7. )
  8. GROUP BY TIPO
  #5 (permalink)  
Antiguo 14/02/2011, 05:55
Avatar de aniMAYtions  
Fecha de Ingreso: diciembre-2007
Ubicación: Granada
Mensajes: 519
Antigüedad: 16 años, 11 meses
Puntos: 2
Respuesta: problema con recuento de registros

Pues chic@, no sé cómo estaré esta mañana que no me sale la consulta.
Me da el error #1248 - Every derived table must have its own alias .
Pero bueno, me exigen rapidez y he optado por hacerlo de la otra forma que se me ocurrió más pronto.
Aunque me gustaría, para optimizar la aplicación, aplicar el cambio que me has sugerido.

Saludos y buen dia!!
  #6 (permalink)  
Antiguo 14/02/2011, 05:58
Avatar de Heimish2000  
Fecha de Ingreso: enero-2011
Ubicación: Madrid
Mensajes: 844
Antigüedad: 13 años, 10 meses
Puntos: 89
Respuesta: problema con recuento de registros

Código SQL:
Ver original
  1. SELECT TIPO, SUM(PUB), SUM(PRI)
  2. FROM
  3. (
  4. SELECT TIPO, CASE WHEN CARACTER = 'Público' THEN '1' ELSE '0' END AS PUB,
  5. CASE WHEN CARACTER = 'Privado' THEN '1' ELSE '0' END AS PRI
  6. FROM TIPOS
  7. ) AS MITABLA
  8. GROUP BY TIPO
  #7 (permalink)  
Antiguo 14/02/2011, 06:38
Avatar de aniMAYtions  
Fecha de Ingreso: diciembre-2007
Ubicación: Granada
Mensajes: 519
Antigüedad: 16 años, 11 meses
Puntos: 2
Respuesta: problema con recuento de registros

Muchas gracias de nuevo. Pero sigo intentando que me salgan todos los tipos aunque no haya registros coincidentes en la tabla sservicios y no lo logro!!
Siento ser pesada, pero a ver si pudes darme una solucion..
Gracias!!
  #8 (permalink)  
Antiguo 14/02/2011, 09:02
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 17 años
Puntos: 2658
Respuesta: problema con recuento de registros

A mi entender el problema de la consulta es la lógica con la que se está elaborando.
En el primer post dice que desea saber cuál es la cantidad y tipos de servicios brindados a las empresas de la zona asignada, aunque esa cantidad sea cero, pero está basando la consulta en los servicios efectivamente brindados. Eso no está bien. SI lo que que se desea es conocer la cantidad y tipo de servicios brindados a las empresas cliente, la primer tabla que contiene todas las posibilidades no es servicio, es empresas.
Es decir, que lo primero a determinar es cuáles son las empresas del ámbito que se analizarán:
Código MySQL:
Ver original
  1. SELECT id_empresa
  2. FROM empresas e
  3. WHERE id_comunidad = valorbuscado;
De esas empresas, hay que averiguar las que tuvieron servicios, publicos o privados:
Código MySQL:
Ver original
  1.     e.id_empresa, IFNULL(s.id_servicio,0) id_servicio
  2.     empresas e
  3.     LEFT JOIN servicio s ON s.id_empresa = e.id_empresa
  4. WHERE e.id_comunidad = valorbuscado;
Esta tabla devolverá todas los id de empresas, y NULL donde no haya servicios, entonces hay que determinar qué tipos de servicio fueron aquellos que fueron válidos, pero en vez de contarlos, hay que sumarlos para que pueda controlarse en NULL:
Código MySQL:
Ver original
  1.     e.id_empresa,
  2.     SUM(IF(c.caracter = 'Público',1, 0)) Publico,
  3.     SUM(IF(c.caracter = 'Privado',1, 0)) Privado
  4.     empresas e
  5.     LEFT JOIN servicio s ON s.id_empresa = e.id_empresa
  6.     INNER JOIN  caracte c ON s.id_caracter = c.id_caracter
  7. WHERE e.id_comunidad = valorbuscado
  8. GROUP BY e.id_empresa;
Aquí hay algunas observaciones a realizar:
- Si el carácter del servicio es un valor binario (de sólo dos valores posibles), crear una tabla para administrarlo, es innecesario. Con un campo BIT o BOOL alcanzaría si predefines el estado; e incluso con un ENUM sería suficiente.
- Si el id_caracter está contenido en la tabla servicio, no se necesita en la tabla tipo, o al menos se vuelve superfluo. Si lo vas a mantener en la tabla tipo, hay que eliminarlo de servicio porque se vuelve redundante, y allí sí se requiere incluir la tabla tipo. en el INNER JOIN
- Cruzar la tabla de técnicos no se requiere en tu consulta, porque no estás listando los técnicos, sólo los tipos de servicio, y para ello saber qué técnico lo realizó es irrelevante. No aporta ni saca nada, por lo tanto el JOIN con esa tabla se vuelve superfluo.
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)

Etiquetas: registros
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:16.