Ver Mensaje Individual
  #7 (permalink)  
Antiguo 12/03/2012, 17:37
nosoul
 
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!