2013-06-15 25 views
11

Zabawne, że jeszcze tego nie widziałem!Wiele-do-wielu na tym samym stole

Nigdy nie przyszło mi do głowy, że można mieć stosunek "wielu do wielu" przy jednym stole - dopóki nie zacząłem pracować nad systemem, w którym użytkownicy mogą się "zaprzyjaźnić" ze sobą (sieci społecznościowe).

Standardowa tabela przeglądowa, przynajmniej w taki sposób, w jakim jestem przyzwyczajona, nie jest tutaj odpowiednia. Pozwala na proste:

Tabela użytkownika ma kolumnę "id" i "nazwa".

Tabela zależności użytkownika zawiera "uid1" i "uid2", reprezentujące użytkowników będących "przyjaciółmi" lub "pąków" lub "znajomych" lub "cokolwiek innego".

Szybko staje się oczywiste, jaki jest tu problem: uid1 i uid2 to ten sam typ danych z tej samej kolumny z tej samej tabeli, co oznacza, że ​​unikalne klucze stają się wadliwe.

Np uid1 = 1 uid2 = 2

jest taka sama jak:

uid1 = 2 uid2 = 1

I dlatego mógł wrócić 2 rekordy lub 0 rekordy jeśli zapytanie jest wykonane nieprawidłowo.

W duchu dobrego zaprojektowania tabeli nie chcę skanować całej tabeli dwukrotnie, aby sprawdzić istniejące wartości.

Czy istnieje jakaś sztuczka do radzenia sobie z tym? To jest pytanie projektowe, które nigdy nie przyszło mi do głowy, i to mnie irytuje, ponieważ wiem, że jest jakaś prosta sztuczka, aby to zadziałało.

Zanim zapytasz, nie próbowałem niczego, ponieważ już widzę, że mój ulubiony sposób porównywania rzeczy (tabele przeglądowe) jest niewystarczający dla moich potrzeb tutaj i potrzebuję pomocy - nie mogę znaleźć niczego .. na SO lub Google :(

z góry dzięki

+0

O co pytasz? – Umbrella

+0

Możesz * mieć * relację M-M między tabelą a nią samą, używając tej samej metody "stołu stolarskiego", jak w przypadku każdej innej relacji M-m. – Umbrella

+0

Oczywiście możesz mieć m-m w jednej tabeli - gdzie użytkownicy odnoszą się do siebie. Think facebook lub myspace lub cokolwiek innego, wielu użytkowników może mieć wielu przyjaciół jako użytkowników - jest to relacja wiele do wielu na samym stole użytkownika, a nie między dwiema tabelami. @Umbrella Pytam, jak powiązać użytkowników ze sobą - jak to zrobić, aby uniknąć duplikowania wpisów. Będę edytować, aby było bardziej jasne. – dudewad

Odpowiedz

7

co oznacza, że ​​stają się unikatowe klucze wadliwy

uid1 = 1 uid2 = 2 

jest taka sama jak:

uid1 = 2 uid2 = 1 

Nie, nie jest.

Na przykład na Facebooku, mam wielu klientów, którzy wysłali prośby o zostania "przyjaciółmi", których nigdy nie akceptowałem ... Ponieważ są zwykłymi znajomymi.

W tym samym kierunku mogłem zaznaczyć kilku ludzi jako najlepszych przyjaciół, a oni nie odwzajemniali się i odwrotnie. A może ignoruję kilka, a nie są.

Zasadniczo jest o wiele więcej informacji w krotce (uid1, uid2) niż zwykłe identyfikatory.

Upewnij się, że nigdy nie musisz zajmować się takimi sytuacjami przed podjęciem decyzji o dodaniu np. Ograniczenie uid1 < uid2 na stole.

+1

Tak, ale dodanie więcej danych na temat związku jest poza zakresem tego pytania, po prostu pytam o bezpośredni związek (pozostawiając "potwierdzone" przyjaźnie i typ przyjaźni jak "najlepszy" z tego). Naprawdę podoba mi się ograniczenie posiadania uid1 dudewad

+0

Cóż, jeśli uważasz, że nie potrzebujesz dwóch wierszy na relację, ograniczenie jest dobrym sposobem na wymuszenie wstawienia niepotrzebnych wierszy - masz gwarancję, że wszystkie krotki będą niepowtarzalne. Pamiętaj jednak, że mimo to musisz sprawdzić obie kolumny, aby pobrać wszystkie relacje. –

+0

Ale potem, na dłuższą metę, skończy się przechowywanie, niezależnie od tego, jak bardzo starasz się tego uniknąć. Tak więc musisz użyć dwóch wierszy na połączenie. X jest przyjacielem z Y, po prostu mówiąc, nie jest odpowiednikiem Y jest przyjacielem X. Nawet jeśli udajemy, że jest w wielu związkach społecznych. –

2

To nie jest takie rzadkie.

Zazwyczaj wykonuje się to, że istnieje tabela, jak w większości wielu relacji, które składają się z dwóch kolumn, z których każda jest identyfikatorem dwóch tabel, które tworzą klucz podstawowy.

Jak podano userId1 i userId2. Atrybuty, jeśli to konieczne, można dodać do relacji (np. Klasyfikacja przyjaźni).

Gdy użytkownik 1 zaprzyjaźnia się z użytkownikiem 2, zwykle są to dwie wstawki (1,2) i (2,1).

Taki sam rodzaj rzeczy z defriending, musi być dwa usunięte.

Użytkownik może otrzymać użytkownika, który jest jego przyjacielem i może to mieć kluczowe znaczenie dla rzeczywistego działania systemu. Jeśli użytkownik może przeglądać tylko zdjęcia swoich znajomych, to jeśli nie jest przyjacielem dla siebie, niektóre systemy mogą nie pozwolić mu zobaczyć swoich zdjęć.

Jest to bardzo zależne od tego, w jaki sposób aplikacja jest zapisywana na bazie danych.

+1

Ooh, co jest interesujące. Więc mówisz, że nie jest źle mieć dwie wersje tego samego związku? Czy to nie oznacza, że ​​masz stół, który jest dosłownie 2x tak duży, jak byś chciał? Poza tym, skąd wiesz, że jest to "typowa" praktyka? (po prostu ciekawy) – dudewad

+1

Myślę, że to jest podejście, które bym podjął, podczas gdy obie kolumny zawierają identyfikatory użytkowników, pierwsza kolumna miałaby być friender, druga kolumna jako przyjaciel. – Matt

+1

Przyszło mi do głowy, chociaż dość zabawny, to właśnie ten scenariusz skłonił mnie do zadawania tego pytania. Wydaje mi się, że są to "technicznie" zduplikowane wpisy i że nie można. W żadnym razie nie jestem żadnym DBA ... co z komentarzem @ Denisa o ograniczaniu kolumn, aby uid1 był zawsze mniejszy niż uid2? Możesz to zrobić w kodzie wstawiania. Myśli o tym? – dudewad

6

Jeśli związek, który opisujesz jest symetryczny, tak jak w "Bob jest przyjacielem Joe" znaczy "Joe jest także przyjacielem Boba", to możesz w swoim kodzie upewnić się, że mniejszy z 2 użytkowników Identyfikatory idą do pierwszej kolumny, a większa do drugiej. To ograniczenie zapewnia, że ​​rekordy w tabeli odnośników będą unikalne. Oznacza to również, że podczas wyszukiwania należy zwykle przeszukać obie kolumny.

Na przykład, jeśli próbujesz zdobyć wszystkich przyjaciół Boba, musisz zapytać o rekordy, które mają identyfikator Boba w obu kolumnach. To prowadzi do nieco więcej kodu i prawdopodobnie wpływa na wydajność.

Jeśli związek może być asymetryczny, tak jak w "Bob jest przyjacielem Joe", niekoniecznie oznacza "Joe jest także przyjacielem Boba", to potrzebujesz 2 wpisów dla każdej pary użytkowników: Bob - Joe i Joe - Bob. Oznacza to, że Twoja tablica przeglądowa będzie zawierać dwa razy więcej wpisów, a także, że twoja strona jest bardzo przyjazna stalkerom: D Oczywiście, nadal możesz wybrać zastosowanie tego systemu, nawet jeśli twoja relacja jest symetryczna.

Korzystając z tej metody, jeśli chcesz uzyskać wszystkich przyjaciół Boba, musisz wybrać rekordy z identyfikatorem Boba w pierwszej kolumnie. Możliwe, że może to oznaczać szybsze wyszukiwanie i mniej kodu do napisania, ale znowu oznacza to, że zajmujesz więcej miejsca w bazie danych.

+0

Oczywiście danych osobowych nie będą dostarczane osobom, które nie zostały wymienione jako przyjaciel. :RE – dudewad

1

Zgadzam się z tym, co powiedzieli inni, to nie jest zły pomysł, aby mieć 2 wkładki do związku (1: 2 i 2: 1). Pomaga to w rozszerzeniu niektórych funkcji, które powszechnie można znaleźć w nowoczesnych sieciach społecznościowych. Niektóre przypadki praktycznego zastosowania, które mogę wymyślić, to opis relacji lub innych atrybutów. Podczas gdy osoby pozostają przyjaciółmi, zachowują różne ustawienia względem siebie. W relacji 1: 2 Bob śledzi aktualizacje Joego i ma go na liście najlepszych przyjaciół (dodaj kolumnę bff), podczas gdy w 2: 1 Joe nie ma Boba na liście bff i nie dba o to, by śledzić jego posty (następująca kolumna) .

Powiązane problemy