2010-08-23 28 views
6

Supongamos que tengo una entidad llamada de usuario y una amistad existir entre dos usuarios SO para que tengo una tabla 'Usuario' y una tabla de relaciones de 'amistad'cómo representar simétrica de muchos a muchos

USER id firstName LastName 1 taher chhabrawala 2 john Dsouza 3 rahul singh 4 deepak patel

Friendship id id 1 2 1 3 1 4 4 1 4 3

En la tabla anterior YO SOY el almacenamiento de la misma información dos veces, es decir "Taher es un amigo de Deepak y Deepak es un amigo de Taher"

¿hay alguna manera de reducir esta redundancia?

Respuesta

8

Bueno, puedes simplemente asumir que todas las amistades son simétricas y almacenar esa amistad solo una vez, pero eso significa que cuando quieres consultar a todos los amigos de Taher, debes buscar su ID en cualquiera de las columnas.

Alternativamente, podría tener una tabla separada de ID de relación, y luego una tabla de relación de uno a muchos para el usuario. Esto tiene la ventaja de que permitiría las relaciones entre múltiples personas si algún día lo desea y le permitiría agregar metadatos sobre la relación (cuándo comenzó, quién lo sugirió, lo que sea).

User     
Id Name   
1  Taher   
2  Deepak   

Relationship    
Id  StartDate   
1  2010-08-23 

UserRelationship 
RelationshipId UserId 
1    1 
1    2 

Por otro lado, en Facebook, por ejemplo, puedo "hacerme amigo" de alguien y pueden decidir no devolverme el amigo. Si no tiene el enfoque "redundante" que está utilizando ahora, ¿cómo representará esa amistad no recíproca?

+0

fresca Nunca había pensado en el escenario de varias personas Pero para el escenario de dos personas, creo que esto sería más adecuado RelationshipId | User1_Id | User2_Id ¿qué opinas? Y realmente me gustó este enfoque, gracias –

+1

Si coloca una columna User1 y User2 en la misma fila, está realmente de vuelta al principio: si desea encontrar a todos los amigos de Taher, debe buscar cada fila que tiene el ID de Taher como Usuario1 o como Usuario2. –

1

La solución obvia es almacenar solo 1 registro por cada par de amigos. Sin embargo, hace más difícil mantener la singularidad; todas las consultas para obtener/actualizar/eliminar la relación de amigo se vuelven más complejas en comparación con la solución "redundante". Además, la solución con 2 registros le permite mantener solicitudes de amigos (por ejemplo, el usuario A le pide al usuario B que sea un amigo. El usuario B puede confirmar o rechazar esta solicitud). Entonces yo diría que la redundancia es perfectamente válida en este caso.

3

Componga una regla como 'el primer valor de ID es siempre menor que el segundo valor de ID', para que pueda asegurarse de que no haya duplicados.

En ese caso, el par (4,1) no es válido, y el par (4,3) se almacenaría como (3,4).

1

Si decidió utilizar el diseño simétrico, puede ser útil asegurarse de que cada amistad sea siempre bidireccional. Puede probar esto:

CREATE TABLE Friendship 
(UserId1 INT NOT NULL REFERENCES Users (UserId), 
    UserId2 INT NOT NULL, 
    PRIMARY KEY (UserId1, UserId2), 
    FOREIGN KEY (UserId2, UserId1) REFERENCES Friendship (UserId1, UserId2)); 
0

Si almacena las dos filas, se le requerirá para hacer cumplir una regla de integridad que asegura que las amistades siempre vienen en pares.

tienda sólo una fila en la tabla (por ejemplo, FR), y crear una vista SYMFR como

x SELECT, Y DE FR UNIÓN x SELECT como y, y cuando x DE FR

Cuestiones relacionadas