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

[Ayuda][Mysql][Avanzado] Registos unicos y columnas calculadas

Estas en el tema de [Ayuda][Mysql][Avanzado] Registos unicos y columnas calculadas en el foro de Mysql en Foros del Web. Hola, disculpen. tengo una consulta que me esta rompiendo la cabeza. Resulta que tengo unos registros con un codigo, tamaño,id y nombre. Nesecito por medio ...
  #1 (permalink)  
Antiguo 11/03/2012, 21:54
 
Fecha de Ingreso: marzo-2012
Mensajes: 9
Antigüedad: 12 años, 1 mes
Puntos: 0
Pregunta [Ayuda][Mysql][Avanzado] Registos unicos y columnas calculadas

Hola, disculpen.
tengo una consulta que me esta rompiendo la cabeza.
Resulta que tengo unos registros
con un codigo, tamaño,id y nombre.
Nesecito por medio de una consulta restarle el tamaño por uno ingresado y que me devuelva el resultado que mas se acerque a otro valor tambien ingresado(en el ejemplo es 200), ademas nesecito que los codigos no se repitan, es decir me devuelva el mas aproximado por codigo.
El problema es que me devuelve bien la diferencia pero no logro que me devuelva solo 1 por codigo.

RESUMIDO SERIA:
para cada código, el id correspondiente para el registro con menor diferencia


Código PHP:
select Nombrecodigo, (tamaño-400) as diferencia
from objetos
having diferencia
<= 200
order by diferencia asc 
Lo que esta consulta me devuelve es:
Id-----Nombre---Codigo---Diferencia
5-----Pelota1------100------ 30
3-----Pelota2------100------40
2-----Carpa1-------200------45
1-----Pelota3------100------ 60


Y lo que necesito es que me devuelva:

Id-----Nombre -----Codigo ---Diferencia
5-----Pelota1 ------100---------30
2-----Carpa1------- 200---------45


Distinct y group by codigo no me estan funcionando.
El group me esta devolviendo

Id-----Nombre -----Codigo ---Diferencia
1-----Pelota3 ------100---------60
2-----Carpa1------- 200---------45


Agradesco toda su ayuda!

Última edición por nosoul; 11/03/2012 a las 22:15
  #2 (permalink)  
Antiguo 12/03/2012, 00:56
Avatar de Gustavo72  
Fecha de Ingreso: abril-2008
Ubicación: -32.956045,-60.661355
Mensajes: 197
Antigüedad: 16 años
Puntos: 9
Probá usando:

SELECT DISTINCT(codigo), ... FROM ... WHERE ... GROUP BY codigo
  #3 (permalink)  
Antiguo 12/03/2012, 09:48
 
Fecha de Ingreso: marzo-2012
Mensajes: 9
Antigüedad: 12 años, 1 mes
Puntos: 0
Respuesta: [Ayuda][Mysql][Avanzado] Registos unicos y columnas calculadas

Sucede lo mismo que en el ejemplo que yo puse cuando lo uso.
Si uso group by,
me devuelve los primeros Id de objeto que encuentra con los codigos diferentes y el ordenamiento por la menor diferencia no tiene efecto

Última edición por nosoul; 12/03/2012 a las 10:05
  #4 (permalink)  
Antiguo 12/03/2012, 11:02
Avatar de Gustavo72  
Fecha de Ingreso: abril-2008
Ubicación: -32.956045,-60.661355
Mensajes: 197
Antigüedad: 16 años
Puntos: 9
Respuesta: [Ayuda][Mysql][Avanzado] Registos unicos y columnas calculadas

Cita:
Iniciado por nosoul Ver Mensaje
Sucede lo mismo que en el ejemplo que yo puse cuando lo uso.
Si uso group by,
me devuelve los primeros Id de objeto que encuentra con los codigos diferentes y el ordenamiento por la menor diferencia no tiene efecto
pero el HAVING y el ORDER BY no los tenés que eliminar... Sería así:

Código MySQL:
Ver original
  1. SELECT DISTINCT(codigo), Nombre, (tamaño-400) as diferencia
  2. FROM objetos HAVING diferencia<= 200 GROUP BY codigo ORDER BY diferencia

Y si no funciona probá esto otro:

Código MySQL:
Ver original
  1. SELECT DISTINCT(codigo), Nombre, diferencia FROM
  2. (SELECT codigo, Nombre, (tamaño-400) as diferencia FROM objetos HAVING diferencia<=200 ORDER BY diferencia) AS t
  3. GROUP BY codigo ORDER BY diferencia
__________________
Saludos.

Gustavo
  #5 (permalink)  
Antiguo 12/03/2012, 13:43
Colaborador
 
Fecha de Ingreso: enero-2007
Ubicación: México
Mensajes: 2.097
Antigüedad: 17 años, 3 meses
Puntos: 447
Respuesta: [Ayuda][Mysql][Avanzado] Registos unicos y columnas calculadas

Hola nosoul:

Hay un problema con el código de Gustavo72, para este caso la cláusula DISTINCT no sirve pues hay que recordar que cuando se lista más de un campo SE EXCLUYEN SÓLO AQUELLOS REGISTROS DONDE TODOS LOS CAMPOS SEAN IGUALES, no sólo uno. Es por eso que vuelven a aparecer los mismos registros. Veamos si este ejemplo les deja más claro el problema:

Código MySQL:
Ver original
  1. mysql> SELECT id, nombre  FROM tabla;
  2. +------+----------+
  3. | id   | nombre   |
  4. +------+----------+
  5. |    1 | uno      |
  6. |    1 | uno      |
  7. |    1 | otro uno |
  8. |    2 | uno      |
  9. +------+----------+
  10. 4 rows in set (0.08 sec)
  11.  
  12. mysql> SELECT DISTINCT id  FROM tabla;
  13. +------+
  14. | id   |
  15. +------+
  16. |    1 |
  17. |    2 |
  18. +------+
  19. 2 rows in set (0.00 sec)
  20.  
  21. mysql> SELECT DISTINCT nombre  FROM tabla;
  22. +----------+
  23. | nombre   |
  24. +----------+
  25. | uno      |
  26. | otro uno |
  27. +----------+
  28. 2 rows in set (0.00 sec)
  29.  
  30. mysql> SELECT DISTINCT id, nombre  FROM tabla;
  31. +------+----------+
  32. | id   | nombre   |
  33. +------+----------+
  34. |    1 | uno      |
  35. |    1 | otro uno |
  36. |    2 | uno      |
  37. +------+----------+
  38. 3 rows in set (0.01 sec)
  39.  
  40. mysql> SELECT DISTINCT (id), nombre  FROM tabla;
  41. +------+----------+
  42. | id   | nombre   |
  43. +------+----------+
  44. |    1 | uno      |
  45. |    1 | otro uno |
  46. |    2 | uno      |
  47. +------+----------+
  48. 3 rows in set (0.00 sec)

Observen en el último caso poner entre paréntesis el campo id es exactamente lo mismo que no ponerlo, pues como dije anteriormente la comparación se hace sobre la totalidad de los campos. Es por eso que cuando se incluyen los dos campos sólo se excluye el id=1 con nombre=uno pues este SI ESTÁ DUPLICADO.

Ahora bien, con respecto al problema original, no me queda del todo claro qué es lo que quieres hacer, pero según el planteamiento veamos si esto te sirve.

Supongamos que tenemos estos datos de ejemplo:

Código MySQL:
Ver original
  1. mysql> SELECT * FROM tabla;
  2. +------+---------+--------+---------+
  3. | id   | nombre  | codigo | tamanio |
  4. +------+---------+--------+---------+
  5. |    1 | Pelota3 |    100 |     420 |
  6. |    2 | Carpa1  |    200 |     445 |
  7. |    3 | Pelota2 |    100 |     440 |
  8. |    4 | Carpa2  |    200 |     340 |
  9. |    5 | Carpa3  |    100 |     350 |
  10. |    6 | Pelota4 |    100 |     380 |
  11. +------+---------+--------+---------+
  12. 6 rows in set (0.00 sec)

Si quisiéramos obtener aquellos productos PARA CADA CATEGORÍA con la menor diferencia con respecto a un tamaño de 400 tendríamos que hacer el siguiente procedimiento (espero no extenderme mucho en el planteamiento, pero quiero dejarles lo más claro posible la lógica de la consulta, pues este tipo de consultas estoy seguro que les servirá en el futuro). Si obtenemos las diferencias con respecto a un tamaño base de 400 obtenemos lo siguiente:

Código MySQL:
Ver original
  1. mysql> SELECT id, nombre, codigo, tamanio, tamanio-400 diferencia FROM tabla;
  2. +------+---------+--------+---------+------------+
  3. | id   | nombre  | codigo | tamanio | diferencia |
  4. +------+---------+--------+---------+------------+
  5. |    1 | Pelota3 |    100 |     420 |         20 |
  6. |    2 | Carpa1  |    200 |     445 |         45 |
  7. |    3 | Pelota2 |    100 |     440 |         40 |
  8. |    4 | Carpa2  |    200 |     340 |        -60 |
  9. |    5 | Carpa3  |    100 |     350 |        -50 |
  10. |    6 | Pelota4 |    100 |     380 |        -20 |
  11. +------+---------+--------+---------+------------+
  12. 6 rows in set (0.00 sec)

Observen el primer detalle que quiero hacer notar, LAS DIFERENCIAS PUEDEN SER TANTO POSITIVAS COMO NEGATIVAS, es decir tamaños más grandes o más pequeños con respecto a la base. si no interesa en realidad el signo pueden hacer uso de la función ABS para manejar absolutos. Ahora bien, como quieren obtener las mínimas diferencias POR CATEGORÍA pueden hacer algo como esto:

Código MySQL:
Ver original
  1. mysql> SELECT codigo, MIN(ABS(tamanio-400)) diferencia FROM tabla
  2.     -> GROUP BY codigo;
  3. +--------+------------+
  4. | codigo | diferencia |
  5. +--------+------------+
  6. |    100 |         20 |
  7. |    200 |         45 |
  8. +--------+------------+
  9. 2 rows in set (0.00 sec)

Ahora bien, esa información ES LA QUE DEBEN TOMAR EN CUENTA PARA FILTRAR LA INFORMACIÓN. Una manera de hacerlo (que no la única y posiblemente no la mejor) sería haciendo esto:

Código MySQL:
Ver original
  1. mysql> SELECT T1.* FROM tabla T1
  2.     -> INNER JOIN
  3.     -> (SELECT codigo, MIN(ABS(tamanio-400)) diferencia
  4.     -> FROM tabla GROUP BY codigo) T2
  5.     -> ON T1.codigo = T2.codigo AND ABS(T1.tamanio - 400) = T2.diferencia
  6.     -> ORDER BY codigo;
  7. +------+---------+--------+---------+
  8. | id   | nombre  | codigo | tamanio |
  9. +------+---------+--------+---------+
  10. |    1 | Pelota3 |    100 |     420 |
  11. |    6 | Pelota4 |    100 |     380 |
  12. |    2 | Carpa1  |    200 |     445 |
  13. +------+---------+--------+---------+
  14. 3 rows in set (0.03 sec)

Observen que para el código 100 aparecen dos registros PUES AMBOS TIENEN UNA DIFERENCIA DE 20 UNA HACIA ARRIBA Y OTRA HACIA ABAJO. Para el caso de del codigo 200 sólo muestra uno, pues los otros registros tienen una diferencia de 50 y 60 respectivamente.

Espero que con este ejercicio puedas obtener tu consulta, cualquier duda la comentas en el foro

Saludos
Leo.
  #6 (permalink)  
Antiguo 12/03/2012, 14:37
Avatar de Gustavo72  
Fecha de Ingreso: abril-2008
Ubicación: -32.956045,-60.661355
Mensajes: 197
Antigüedad: 16 años
Puntos: 9
Respuesta: [Ayuda][Mysql][Avanzado] Registos unicos y columnas calculadas

Cita:
Iniciado por leonardo_josue Ver Mensaje
SE EXCLUYEN SÓLO AQUELLOS REGISTROS DONDE TODOS LOS CAMPOS SEAN IGUALES
Lo que pasa es que te olvidaste de ponerle GROUP BY id a todas las pruebas que hiciste.
Probalo y vas a ver que sí funciona.
__________________
Saludos.

Gustavo
  #7 (permalink)  
Antiguo 12/03/2012, 17:37
 
Fecha de Ingreso: marzo-2012
Mensajes: 9
Antigüedad: 12 años, 1 mes
Puntos: 0
Respuesta: [Ayuda][Mysql][Avanzado] Registos unicos y columnas calculadas

Cita:
Iniciado por leonardo_josue Ver Mensaje
Hola nosoul:

Hay un problema con el código de Gustavo72, para este caso la cláusula DISTINCT no sirve pues hay que recordar que cuando se lista más de un campo SE EXCLUYEN SÓLO AQUELLOS REGISTROS DONDE TODOS LOS CAMPOS SEAN IGUALES, no sólo uno. Es por eso que vuelven a aparecer los mismos registros. Veamos si este ejemplo les deja más claro el problema:

Código MySQL:
Ver original
  1. mysql> SELECT id, nombre  FROM tabla;
  2. +------+----------+
  3. | id   | nombre   |
  4. +------+----------+
  5. |    1 | uno      |
  6. |    1 | uno      |
  7. |    1 | otro uno |
  8. |    2 | uno      |
  9. +------+----------+
  10. 4 rows in set (0.08 sec)
  11.  
  12. mysql> SELECT DISTINCT id  FROM tabla;
  13. +------+
  14. | id   |
  15. +------+
  16. |    1 |
  17. |    2 |
  18. +------+
  19. 2 rows in set (0.00 sec)
  20.  
  21. mysql> SELECT DISTINCT nombre  FROM tabla;
  22. +----------+
  23. | nombre   |
  24. +----------+
  25. | uno      |
  26. | otro uno |
  27. +----------+
  28. 2 rows in set (0.00 sec)
  29.  
  30. mysql> SELECT DISTINCT id, nombre  FROM tabla;
  31. +------+----------+
  32. | id   | nombre   |
  33. +------+----------+
  34. |    1 | uno      |
  35. |    1 | otro uno |
  36. |    2 | uno      |
  37. +------+----------+
  38. 3 rows in set (0.01 sec)
  39.  
  40. mysql> SELECT DISTINCT (id), nombre  FROM tabla;
  41. +------+----------+
  42. | id   | nombre   |
  43. +------+----------+
  44. |    1 | uno      |
  45. |    1 | otro uno |
  46. |    2 | uno      |
  47. +------+----------+
  48. 3 rows in set (0.00 sec)

Observen en el último caso poner entre paréntesis el campo id es exactamente lo mismo que no ponerlo, pues como dije anteriormente la comparación se hace sobre la totalidad de los campos. Es por eso que cuando se incluyen los dos campos sólo se excluye el id=1 con nombre=uno pues este SI ESTÁ DUPLICADO.

Ahora bien, con respecto al problema original, no me queda del todo claro qué es lo que quieres hacer, pero según el planteamiento veamos si esto te sirve.

Supongamos que tenemos estos datos de ejemplo:

Código MySQL:
Ver original
  1. mysql> SELECT * FROM tabla;
  2. +------+---------+--------+---------+
  3. | id   | nombre  | codigo | tamanio |
  4. +------+---------+--------+---------+
  5. |    1 | Pelota3 |    100 |     420 |
  6. |    2 | Carpa1  |    200 |     445 |
  7. |    3 | Pelota2 |    100 |     440 |
  8. |    4 | Carpa2  |    200 |     340 |
  9. |    5 | Carpa3  |    100 |     350 |
  10. |    6 | Pelota4 |    100 |     380 |
  11. +------+---------+--------+---------+
  12. 6 rows in set (0.00 sec)

Si quisiéramos obtener aquellos productos PARA CADA CATEGORÍA con la menor diferencia con respecto a un tamaño de 400 tendríamos que hacer el siguiente procedimiento (espero no extenderme mucho en el planteamiento, pero quiero dejarles lo más claro posible la lógica de la consulta, pues este tipo de consultas estoy seguro que les servirá en el futuro). Si obtenemos las diferencias con respecto a un tamaño base de 400 obtenemos lo siguiente:

Código MySQL:
Ver original
  1. mysql> SELECT id, nombre, codigo, tamanio, tamanio-400 diferencia FROM tabla;
  2. +------+---------+--------+---------+------------+
  3. | id   | nombre  | codigo | tamanio | diferencia |
  4. +------+---------+--------+---------+------------+
  5. |    1 | Pelota3 |    100 |     420 |         20 |
  6. |    2 | Carpa1  |    200 |     445 |         45 |
  7. |    3 | Pelota2 |    100 |     440 |         40 |
  8. |    4 | Carpa2  |    200 |     340 |        -60 |
  9. |    5 | Carpa3  |    100 |     350 |        -50 |
  10. |    6 | Pelota4 |    100 |     380 |        -20 |
  11. +------+---------+--------+---------+------------+
  12. 6 rows in set (0.00 sec)

Observen el primer detalle que quiero hacer notar, LAS DIFERENCIAS PUEDEN SER TANTO POSITIVAS COMO NEGATIVAS, es decir tamaños más grandes o más pequeños con respecto a la base. si no interesa en realidad el signo pueden hacer uso de la función ABS para manejar absolutos. Ahora bien, como quieren obtener las mínimas diferencias POR CATEGORÍA pueden hacer algo como esto:

Código MySQL:
Ver original
  1. mysql> SELECT codigo, MIN(ABS(tamanio-400)) diferencia FROM tabla
  2.     -> GROUP BY codigo;
  3. +--------+------------+
  4. | codigo | diferencia |
  5. +--------+------------+
  6. |    100 |         20 |
  7. |    200 |         45 |
  8. +--------+------------+
  9. 2 rows in set (0.00 sec)

Ahora bien, esa información ES LA QUE DEBEN TOMAR EN CUENTA PARA FILTRAR LA INFORMACIÓN. Una manera de hacerlo (que no la única y posiblemente no la mejor) sería haciendo esto:

Código MySQL:
Ver original
  1. mysql> SELECT T1.* FROM tabla T1
  2.     -> INNER JOIN
  3.     -> (SELECT codigo, MIN(ABS(tamanio-400)) diferencia
  4.     -> FROM tabla GROUP BY codigo) T2
  5.     -> ON T1.codigo = T2.codigo AND ABS(T1.tamanio - 400) = T2.diferencia
  6.     -> ORDER BY codigo;
  7. +------+---------+--------+---------+
  8. | id   | nombre  | codigo | tamanio |
  9. +------+---------+--------+---------+
  10. |    1 | Pelota3 |    100 |     420 |
  11. |    6 | Pelota4 |    100 |     380 |
  12. |    2 | Carpa1  |    200 |     445 |
  13. +------+---------+--------+---------+
  14. 3 rows in set (0.03 sec)

Observen que para el código 100 aparecen dos registros PUES AMBOS TIENEN UNA DIFERENCIA DE 20 UNA HACIA ARRIBA Y OTRA HACIA ABAJO. Para el caso de del codigo 200 sólo muestra uno, pues los otros registros tienen una diferencia de 50 y 60 respectivamente.

Espero que con este ejercicio puedas obtener tu consulta, cualquier duda la comentas en el foro

Saludos
Leo.
Muchas gracias a todos,
Y leonardo, Gracias a ti por iluminarme con tu conocimiento, nisiquiera concidere condicionar el join para obtener ese resultado.
Funciono de maravillas y realmente me siento muy tranquilo ahora que lo pude arreglar efecientemente, GRACIAS A TI.

Al resto, muchisimas gracias por su predisposicion y estar ahi!
  #8 (permalink)  
Antiguo 12/03/2012, 17:59
 
Fecha de Ingreso: marzo-2012
Mensajes: 9
Antigüedad: 12 años, 1 mes
Puntos: 0
Respuesta: [Ayuda][Mysql][Avanzado] Registos unicos y columnas calculadas

Una consulta adicional. no puedo usar en una clausula ON de un INNER JOIN una columna calculada?
para ecitarme volver a hacer la cuenta, poque si en ves de una resta, es una susecion de multiplicaciones restada por otras multiplicaciones, gasto bastantes recursos

Etiquetas: group, registos, repetidos
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:14.