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

Duda al Normalizar una tabla Amigos

Estas en el tema de Duda al Normalizar una tabla Amigos en el foro de Bases de Datos General en Foros del Web. Hola a todos, No se si es titulo del post estará bien...pero pos aqui va mi inquietud: tengo una tabla llamada usuarios, y el objetivo ...
  #1 (permalink)  
Antiguo 06/05/2009, 08:21
Avatar de junarry  
Fecha de Ingreso: marzo-2007
Ubicación: colombia
Mensajes: 113
Antigüedad: 17 años, 1 mes
Puntos: 0
Duda al Normalizar una tabla Amigos

Hola a todos,

No se si es titulo del post estará bien...pero pos aqui va mi inquietud:

tengo una tabla llamada usuarios, y el objetivo es que un usuario puede tener varios usuarios como amigos........lo que indica que se crea una relacion varios a varios....aqui esta mi propuesta



la tabla usuarios_1 es una tabla espejo de la tabla usuarios, y la tabla amigos es la entidad derivada que me permite ralacionar los usuarios.

mi mayor duda se presenta en la forma de llenar la entidad derivada:

CodInt | CodUs | Codusami
______________________
1...................1..........2
2...................1.............3
3...................1.............4
4...................2..........1
5...................2.............3

Ustedes que opinan de esa relacion, de ese diseño?

Si ven los datos que estan en negrilla.....me imagino que eso no se podria dar por que habria redundancio...o no?

Nota: no le hagan caso a los puntos....solo los coloque para poder separar los datos!!

Última edición por junarry; 06/05/2009 a las 08:29
  #2 (permalink)  
Antiguo 06/05/2009, 08:50
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 16 años, 5 meses
Puntos: 2658
Respuesta: Duda al Normalizar una tabla Amigos

En principio está bien, pero si la tabla Usuarios1 es un espejo de la otra, en realidad existen entonces dos tablas: La tabla USUARIOS() y la tabla AMIGOS. En la segunda tanto el campo CodUs como CodUsAmi serían FK de la tabla Usuarios, solamente que el primero sería asignado al código del usuario primario, y el segundo al usuario amigo del primero.
En esencia es casi nada más que un índice relacional, la relación sigue siendo N:N, pero con dos tablas.
Por otro lado, en este punto el campo CodInt, no tiene sentido de existir, porque si esa es PK existe la posibilidad de que se registre una duplicación de claves, y además no controlarías la posibilidad de dos registros del tipo (A,B) y (B,A), que son iguales funcionalmente.

Resumiendo: Si eliminas la tercera tabla, el resultado es correcto igualmente, y más eficiente que como lo planteas ahora.
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #3 (permalink)  
Antiguo 06/05/2009, 09:30
Avatar de junarry  
Fecha de Ingreso: marzo-2007
Ubicación: colombia
Mensajes: 113
Antigüedad: 17 años, 1 mes
Puntos: 0
Respuesta: Duda al Normalizar una tabla Amigos

Gracias popr responder!!

mira....dices que deberia eliminar la 3 tabla!...osea la Usuarios_1..no es cierto?.....ponle cuidado que esta tabla acces la creo al yo crear la relación hacia el campo CodUsAmi de la tabla Amigos.....pero pues en escencia si son solo dos tablas...xD!!

Lo otro......El campo CodInt de la tabla Amigos sí es Pk pero pues lo puse por que es una regla no!!....se supone que en una tabla debe existir una campo que haga de llave primaria.......y no entendi este pedasito y además no controlarías la posibilidad de dos registros del tipo (A,B) y (B,A), que son iguales funcionalmente....??...

Pero si viste como llene con registros la tabla amigos, si viste lo que resalte en negrilla? estaria bien esa forma de llenar la tabla?....para así en una consulta saber cuales son los amigos de quien y cuales amigos hay en comun entre dos usuarios???
  #4 (permalink)  
Antiguo 06/05/2009, 10:14
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 16 años, 5 meses
Puntos: 2658
Respuesta: Duda al Normalizar una tabla Amigos

Una clave primaria no es necesariamente siempre un campo numérico (autoincremental o no). Es un campo o conjunto de campos que identifican univocamente un registro en una tabla dada.
Esa sería la definición de PK.
En este contexto, lo que quiero decirte es que el campo CodInt carece de sentido porque la clave debería ser la combinación de (CodUs, CodUsAmi)... Esto es, una clave compuesta de dos campos.
Lo que significa que no podrás controlar la duplicidad de FK en el caso de ser CodInt una PK, es porque si no defines la relación (CodUs, CodUsAmi) como UNIQUE, entonces podría perfectamente darse el caso de:
CodInt / CodUs / CodUsAmi
1 / 1 / 2
2 / 1 / 2
3 / 1 / 2
Ya que la PK es el primer campo y no los otros dos. Pero si has definido la relación (CodUs, CodUsAmi) como UNIQUE, ¿para qué necesitas entonces el CoInt? En ese caso, en vez de ser solamente UNIQUE la podrías definir como PK y listo... que es precisamente lo que sugiero.
Lo que planteas de que es necesario ese campo, es porque pareciera ser un requisito de la 3FN, pero no es así, porque los dos campos de la relación son determinantes, y según la 3FN el campo de clave se adiciona si ninguno de los atributos de la relación puede ser una clave candidata... cosa que en este caso no se cumple.

¿Se entiende la idea?

Volviendo al principio, el uso de una tabla espejo para almacenar información que ya existe solamente para darle graficación a una relación que se resuelve con una sola tabla, es al menos ineficiente, porque estás duplicando datos, lo que puede tener como consecuencia inconsistencia de datos en la base. Y eso es lo que se pretende evitar cuando se diseña.
SI lo que haces es tener algún proceso que mantenga los datos espejados, resulta ineficiente a nivel de proceso, teniendo en cuenta que eso se resuelve definiendo ambos campos como referidos a la tabla USUARIOS...
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #5 (permalink)  
Antiguo 06/05/2009, 11:45
 
Fecha de Ingreso: enero-2009
Mensajes: 455
Antigüedad: 15 años, 3 meses
Puntos: 11
Respuesta: Duda al Normalizar una tabla Amigos

leyendo lo que nos comenta el buen junarry, su primer post esta bien a como yo lo veo, por otra parte lo que comenta el buen gnzsoloyo tambien es correcto, simplemente, porque no definir en tu tabla transitiva los dos campos que les pasas como FK como PK, es decir, que ambos campos sean la PK de la tabla, asi lo suguiere gnzsoloyo ,si bien entendi, por otra parte una duda que me surge, lo que comentas de las negritas que pusiste, es decir, si en tu tabla tienes

tabla_transitiva

CodInt / CodUs / CodUsAmi
1 1 2
2 1 3
3 1 4
4 2 1
5 2 6
6 3 2

mi duda es, no es del todo correcto?? ahi no estas indicando que el usuario con id=1 tiene de amigo al id=2 y que el id=2 tiene de amigo al id=1 (se podría ver como redundante), pero se puede dar el caso en tu problema en que el usuario id=1 tenga como amigo al usuario id=2, PERO..., que el usuario id=2 no acepte como amigo al id=1?????? esa es mi duda

saludos
  #6 (permalink)  
Antiguo 06/05/2009, 12:46
Avatar de Adolfiten  
Fecha de Ingreso: enero-2008
Ubicación: Frente a mi monitor...
Mensajes: 572
Antigüedad: 16 años, 4 meses
Puntos: 7
Respuesta: Duda al Normalizar una tabla Amigos

Aparentemente todos coincidimos en que no hace falta una tercera tabla.

Yo personalmente optaría por dejar como PK a CodInt, y FK los otros dos campos. Cuando vayas a buscar los amigos de un usuario, vas a tomar un campo, por tanto está bien que haya un registro "1 1 2" y un registro "4 2 1", ¿me explico?

Es más fácil buscar en un campo el id del usuario y en el valor del otro el id del amigo, si no sabés en qué campo tenés el id del usuario se dificulta un poco; tenés que buscar el id en un campo, luego en el otro, e ir tomando el id del amigo.

Para hacer la selección de amigos de un usuario probablemente hagas:

Código SENTENCIA SQL:
Ver original
  1. SELECT *
  2. FROM usuarios u, transitiva t, usuarios uu
  3. WHERE u.CodUs = CODIGO_DEL_USUARIO_AL_QUE_LE_BUSCO_LOS_AMIGOS
  4.       AND t.CodUsAmi = uu.CodUs

Saludos.
  #7 (permalink)  
Antiguo 06/05/2009, 16:04
 
Fecha de Ingreso: enero-2009
Mensajes: 455
Antigüedad: 15 años, 3 meses
Puntos: 11
Respuesta: Duda al Normalizar una tabla Amigos

Cita:
por tanto está bien que haya un registro "1 1 2" y un registro "4 2 1",
coincido contigo
  #8 (permalink)  
Antiguo 06/05/2009, 20:27
Avatar de junarry  
Fecha de Ingreso: marzo-2007
Ubicación: colombia
Mensajes: 113
Antigüedad: 17 años, 1 mes
Puntos: 0
Respuesta: Duda al Normalizar una tabla Amigos

hola gnzsoloyo, no tenia bien clara la 3FN... veo que entonces no seria necesario el campo CodInt...puede que se reduzca el performance de la aplicacion por tener los datos espejados!!...

a mi amigo eulerss le digo que si se llega a llenar la tabla Amigos() de esa forma, si abria redundancia.....io lo planteaba hacer de esa forma, pero me di cuenta que no es la correcta....por que al momento de agregar un amigo, con una relacion 1|2, tendria que hacer inmediatamente un Insert para insertar otro registro pero con la relacion 2|1, entonces lo que hariamos es llenar la base de datos innecesariamente.....no crees?
...tu otra duda....si el usuario 1 pide ser amigo del 2, pero este no acepta...simplemente no se crearia ningun registro 1|2 en la tabla.
  #9 (permalink)  
Antiguo 06/05/2009, 21:00
Avatar de junarry  
Fecha de Ingreso: marzo-2007
Ubicación: colombia
Mensajes: 113
Antigüedad: 17 años, 1 mes
Puntos: 0
Respuesta: Duda al Normalizar una tabla Amigos

Cita:
Iniciado por Adolfiten Ver Mensaje
Aparentemente todos coincidimos en que no hace falta una tercera tabla.

Yo personalmente optaría por dejar como PK a CodInt, y FK los otros dos campos. Cuando vayas a buscar los amigos de un usuario, vas a tomar un campo, por tanto está bien que haya un registro "1 1 2" y un registro "4 2 1", ¿me explico?

Es más fácil buscar en un campo el id del usuario y en el valor del otro el id del amigo, si no sabés en qué campo tenés el id del usuario se dificulta un poco; tenés que buscar el id en un campo, luego en el otro, e ir tomando el id del amigo.

Para hacer la selección de amigos de un usuario probablemente hagas:

Código SENTENCIA SQL:
Ver original
  1. SELECT *
  2. FROM usuarios u, transitiva t, usuarios uu
  3. WHERE u.CodUs = CODIGO_DEL_USUARIO_AL_QUE_LE_BUSCO_LOS_AMIGOS
  4.       AND t.CodUsAmi = uu.CodUs

Saludos.
Hola......mas o menos por ahí va mi propuesta de solucion!!...:

Independiente de si se deja o no el campo CodInt, no es necesario llenar la tabla de esta forma:
CodInt / CodUs / CodUsAmi
1 |1 | 2
2 | 1 | 3
3 | 1 | 4
4 |2 | 1
5 | 2 | 6
6 | 3 | 2

simplemente si ya tenemos una registro con una relacion 1|2 no creamos otro registro con una relacion 2|1, y al momento de buscar los amigos de un usuario lo ariamos de la siguiente forma:

...voy a colocar un ejemplo:

suponiendo que tenemos los siguentes registros en la tabla amigos:
CodInt / CodUs / CodUsAmi
1 | 1 | 2
2 | 1 | 3
3 | 1 | 4
4 | 2 | 5
5 | 5 | 6
6 | 5 | 1
7 | 7 | 1

entonces para encontrar todos los amigos del usuario 1 hariamos primero una consulta como esta: SELECT CodUsAmi FROM AMIGOS WHERE CodUs=1. osea seleccioneme todos los codigos de CodUsAmi donde el codigo de usuario sea = 1...en esta primera consulta me encontraria los siguientes registros:
1 | 1 | 2
2 | 1 | 3
3 | 1 | 4...osea me encontro que solo tiene tres amigos. El 2, 3 y 4..

entonces para seleccionar los otros amigos que faltan hariamos otra consulta pero al revez!!....osea algo asi como esto:
SELECT CodUs FROM AMIGOS WHERE CodUsAmi=1...osea seleccioneme todo los codigos de CodUs donde el CodUsAmi sea =1.......en esta segunda consulta obtendriamos el siguiente resultado:
6 | 5 | 1
7 | 7 | 1...osea que encontro los otros amigos. 5, 7

de este modo ya tendriamos todos los amigo del usuario 1...nos quedaria no se confrontar las dos consultas o algo asi!!...no se!!...unirlas o algo parecido...para así tener en un solo lugar todos los amigos del usuario 1...

Espero me hayan entendido!!!...o si no pregunten......yo pienso que es una buena solucion!!
  #10 (permalink)  
Antiguo 06/05/2009, 22:52
Avatar de Adolfiten  
Fecha de Ingreso: enero-2008
Ubicación: Frente a mi monitor...
Mensajes: 572
Antigüedad: 16 años, 4 meses
Puntos: 7
Respuesta: Duda al Normalizar una tabla Amigos

Se podría usar UNION. También se puede hacer así, pero la diferencia de volumen de datos por un registro más no va a afectar la performance del servidor ni va a ocupar tanto espacio como para que valga la pena un cambio.

Sigo en pro de lo propuesto anteriormente, también está implicado el "no aceptar" el amigo... que de esta otra manera no se puede hacer.

Saludos.
  #11 (permalink)  
Antiguo 07/05/2009, 08:45
 
Fecha de Ingreso: enero-2009
Mensajes: 455
Antigüedad: 15 años, 3 meses
Puntos: 11
Respuesta: Duda al Normalizar una tabla Amigos

Cita:
hola gnzsoloyo, no tenia bien clara la 3FN
como plus para el post, y para los que lo seguimos desde el principio, en teoria hay 5 formas normales, pero en la practica si normalizas hasta la tercera es mas que suficiente

con respecto a mi duda que tenia, que si no se acepta al amigo no se crea el registro, yo opino que se debería de agregar no? es decir, si yo con id=1 tengo de amigo al id=2, entonces en mi tabla

1|1|2

pero si el usuario id=2 no me acepta como amigo, en la tabla no tendría porque aparecer el registro duplicado

2|2|1

ahora bien, si me acepta como amigo se tendrian los dos

1|1|2
2|2|1

lo cual pudiera parecer redundancia como dices, pero como lo comenta Adolfiten
Cita:
Yo personalmente optaría por dejar como PK a CodInt, y FK los otros dos campos. Cuando vayas a buscar los amigos de un usuario, vas a tomar un campo, por tanto está bien que haya un registro "1 1 2" y un registro "4 2 1", ¿me explico?
ahora bien, si en tu planteamiento del problema para ti es lo mismo
1|1|2 que
2|2|1 pues entonces si caidrias en la redundancia, por lo que con un registro bastaría y la busquedas la harias como comentas o como te comentan con un join

saludos
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 00:52.