Vinnaren i pepparkakshustävlingen!
  • 1
  • 2
2011-02-04, 18:33
  #1
Medlem
Luciditys avatar
Jag anser mig kunna många till många relationer någorlunda bra men jag undrar hur man gör att flerar entiteter inom samma tabell har en koppling till varandra. Det enda exemplet jag kommer på nu är att en person kan ha flera andra personer som vänner. Då skulle jag börja med att göra tabellen Person med attributen id och namn. Hur gör man sen?
Citera
2011-02-04, 18:38
  #2
Medlem
AquaRegias avatar
Förstår inte riktigt vad du menar, det är väl ett vanligt många-till-många-förhållande?

Person(id(PK), namn)
Relation(id1(PK, FK), id2(PK, FK))

(taskig namnsättning )
Citera
2011-02-04, 18:47
  #3
Medlem
Luciditys avatar
Citat:
Ursprungligen postat av AquaRegia
Förstår inte riktigt vad du menar, det är väl ett vanligt många-till-många-förhållande?

Person(id(PK), namn)
Relation(id1(PK, FK), id2(PK, FK))

(taskig namnsättning )
Det är det det inte är, eftersom du kan byta plats på id1 och id2 och få en extra rad i databasen. Om vi har två personer med id 1 och 2 så kan en rad i relation-tabellen vara "1, 2" och nästa rad vara "2, 1".

Nästa problem är att om man vill få ut vänner till en person med id 361 så vet man inte vilken av dessa 2 frågorna som ger rätt svar:

Kod:
SELECT id2 FROM Relation WHERE id1='361'
SELECT id1 FROM Relation WHERE id2='361' 
Citera
2011-02-04, 18:48
  #4
Moderator
Protons avatar
Citat:
Ursprungligen postat av Lucidity
Jag anser mig kunna många till många relationer någorlunda bra men jag undrar hur man gör att flerar entiteter inom samma tabell har en koppling till varandra. Det enda exemplet jag kommer på nu är att en person kan ha flera andra personer som vänner. Då skulle jag börja med att göra tabellen Person med attributen id och namn. Hur gör man sen?
Det där är fel sätt att gå i detta fall.

Det där löser man med en vanlig många-till-många-tabell, dvs ett och samma personid kan vara kopplat till 0 eller många andra personidn.

De fall man normalt använder kopplingar i samma tabell till sej själv är om man vill återskapa någon form av hierarki, där en tupel utgör en föräldratupel till en annan tupel. Tänk dej att du vill modellera en vanlig filstruktur där du har mappar och filer. Då skulle man kunna göra såhär:
Kod:
id, parent_id,name
1,null,"/"
2,1,"dev"
3,2,"null"
där har du principen för att modellera en hierarki. "null" har "dev" som parent med hjälp av dess parentid, "dev" har "/" som parent och "/", dvs root, har ingen parent, därav null som parent_id.

Att bygga upp en kompisrelation på detta sätt har ju sina klara begränsningar som du ser. Vad är det som säger att den ena kompisen är högre upp i hierarkin än den andra? Dessutom kommer du få en "kedja" av kompisar, och dessa kompisar måste höra ihop med andra kompisar på ett logiskt sätt för att du ska kunna göra på det här sättet, vilket i längden betyder att alla dina kompisar måste känna varandra, något som inte alltid inträffar i verkligheten, right?
Citera
2011-02-04, 18:52
  #5
Medlem
AquaRegias avatar
Citat:
Ursprungligen postat av Lucidity
Det är det det inte är, eftersom du kan byta plats på id1 och id2 och få en extra rad i databasen. Om vi har två personer med id 1 och 2 så kan en rad i relation-tabellen vara "1, 2" och nästa rad vara "2, 1".

Nästa problem är att om man vill få ut vänner till en person med id 361 så vet man inte vilken av dessa 2 frågorna som ger rätt svar:

Kod:
SELECT id2 FROM Relation WHERE id1='361'
SELECT id1 FROM Relation WHERE id2='361' 

Detta behöver dock inte vara ett problem beroende på omständigheterna. Om du har en community eller liknande där användarna kan skriva vilka deras vänner är så är det ju inte säkert B skriver att h*n är vän med A bara för att A skrivit att h*n är vän med B.

På så sätt kan det vara skillnad mellan "2, 1" och "1, 2".
Citera
2011-02-04, 18:58
  #6
Medlem
Luciditys avatar
Citat:
Ursprungligen postat av AquaRegia
Detta behöver dock inte vara ett problem beroende på omständigheterna. Om du har en community eller liknande där användarna kan skriva vilka deras vänner är så är det ju inte säkert B skriver att h*n är vän med A bara för att A skrivit att h*n är vän med B.

På så sätt kan det vara skillnad mellan "2, 1" och "1, 2".
Det har du rätt i. I det fallet funkar vårat exempel bra. Men ifall man gör som på facebook att båda personerna måste gå med på att vara vänner så skulle det kräva 2 rader i tabellen per vän-koppling.

Citat:
Ursprungligen postat av Proton
Ja det är ju ingen hierarki av kompisar. Ditt exempel med dev/null förstår jag men "kedjan" av kompisar och det du skriver efter är jag inte riktigt med på.
Citera
2011-02-04, 21:28
  #7
Moderator
Protons avatar
Citat:
Ursprungligen postat av Lucidity
Det har du rätt i. I det fallet funkar vårat exempel bra. Men ifall man gör som på facebook att båda personerna måste gå med på att vara vänner så skulle det kräva 2 rader i tabellen per vän-koppling.


Ja det är ju ingen hierarki av kompisar. Ditt exempel med dev/null förstår jag men "kedjan" av kompisar och det du skriver efter är jag inte riktigt med på.
Den kedja som kommer att uppstå om du har relationer inom samma tabell består ju i att du kommer vara kompis med a, a kommer vara kompis med b, b kommer vara kompis med c etc...

Hur hanterar du då fallet när b känner dej, men inte känner f till exempel? I din modell kommer du inte ha utrymme för det, eftersom alla tupler kommer hänga ihop i en lång kedja. I din modell kommer du alltså att utgå från att alla i "kedjan" känner alla, både bakåt och framåt, men så funkar det ju inte i verkligheten du försöker modellera, eller hur?

Verkligheten ser ju snarare ut som ett hjul, med dej själv som nav och dina kompisar som "ekrar" eller vad man nu ska kalla det. bara för att du känner a,b,c,d osv betyder det ju inte att det finns ett beroende mellan dessa, med andra ord behöver inte c känna b och d för att du själv gör det.

Dessutom uppstår ju problem om du helt plötsligt väljer att ta bort en kompis, säg b. Var tar då dina kkompisar c och d vägen? dom kommmer du ju tappa på kuppen i sådana fall, eftersom det inte finns nån naturlig koppling i modellen mellan c och dej själv, den kopplingen var mot b, som du nu har tagit bort.

Blev det tydligare hur jag menar?
Citera
2011-02-04, 22:07
  #8
Medlem
Luciditys avatar
Citat:
Ursprungligen postat av Proton
text
Nu är jag med. Men jag förstår inte hur det du säger passar in i "min model" ifall du menar den modellen som AquaRegia la fram i inlägg #2. Jag ser inga sådana "kedjor" i den.

Det jag hade tänkt mig är som ett Mesh-nätverk: http://upload.wikimedia.org/wikipedi...eshNetwork.png
Varje person är en grön ring i bilden, och om en person är vän med en annan uppstår en koppling.
Om jag använder modellen vi pratat om kommer det behövas 2 rader i relationstabellen för varje relation, det borde gå att lösa med 1 rad tycker jag.

Hur är det bästa sättet att lösa detta enligt dig?
Citera
2011-02-04, 22:20
  #9
Moderator
Protons avatar
Citat:
Ursprungligen postat av Lucidity
Nu är jag med. Men jag förstår inte hur det du säger passar in i "min model" ifall du menar den modellen som AquaRegia la fram i inlägg #2. Jag ser inga sådana "kedjor" i den.

Det jag hade tänkt mig är som ett Mesh-nätverk: http://upload.wikimedia.org/wikipedi...eshNetwork.png
Varje person är en grön ring i bilden, och om en person är vän med en annan uppstår en koppling.
Om jag använder modellen vi pratat om kommer det behövas 2 rader i relationstabellen för varje relation, det borde gå att lösa med 1 rad tycker jag.

Hur är det bästa sättet att lösa detta enligt dig?
Det där ser ju ut som vilken många-till-många-relation som helst, jag förstår inte hur det skulle kunna bli mer än en rad per relation mellan noderna?

Tänk på att många-till-många-förhållandet går bägge vägarna; om vi i relationen säger att du känner a,b och c innebär det implicit att b,c och a känner dej, men däremot finns det inget beroende mellan a,b och c förrän du uttryckligen talar om att de är kompisar med varandra. En rad i tabellen = ett streck i din bild, eller är det jag som missförstått något nu?
Citera
2011-02-05, 01:54
  #10
Medlem
acshighs avatar
Intressant problem Lucidity. En lösning som jag ser det är att det alltid skapas en (1) rad i Relationstabellen vid vänskap och att denna skapas av den som ansöker om vänskapen. Dvs söker ID2 vänskap med ID1 så skapas 2,1 och söker ID1 vänskap med ID2 så skapas 1,2. Kombinationen sätts till unik.
Vi måste då vid sökning i tabellen söka i båda kolumnerna och slå ihop resultatet för att hitta tex ID2s vänner, eftersom han kan hamna i båda kolumnerna. Men det löser iaf problemet med dubbellagring.

Sen är inte dubbellagring alltid ett problem - all data måste inte normaliseras. Man får sätta laddningstid och utvecklingstid och sånt i relation till vad datalagring kostar. Lagring är extremt billigt och kanske är detta ett läge då en annan datamodell är bättre. Facebook och Google jobbar ju en del med Dokumentdatabaser, Bigtable och Key-Value-databaser till exempel. I en dokumentdatabas (ex. MongoDB) skapar du helt enkelt en uppsättning data om ett objekt, som ett XML-träd ungefär. Nackdelarna är att du måste uppdatera på flera ställen ibland och att du dubbellagrar en del data, fördelarna är mkt enkla queries, snabb dataåtkomst (inga serverside joins), mindre last på serverns CPU. Om man vinner på detta eller inte är helt beroende på situationen.
Citera
2011-02-05, 13:33
  #11
Medlem
Luciditys avatar
Citat:
Ursprungligen postat av Proton
text
Citat:
Ursprungligen postat av acshigh
text
Ja det är "1, 2" samt "2, 1" jag pratar om. Totalt 2 rader i tabellen per relation.
Men jag tror det ni försöker säga är att det räcker med 1 av dem också sköter man resten i php.

Psuedo kod när person 412 vill se sina vänner:
Kod:
SELECT id1id2 FROM relation WHERE id1='412' OR id2='412'
for(sql frågan){
    if(
id1==412)
        
//id2 är vän med 412
    
else if(id2==412)
        
//id1 är vän med 412
    
else
        
//kan inte hända

Blir det bra?
__________________
Senast redigerad av Lucidity 2011-02-05 kl. 13:37.
Citera
2011-02-06, 16:20
  #12
Medlem
Mys-Hitlers avatar
Eller enklare:

Kod:
SELECT id1 AS id FROM relation WHERE id2=412
UNION
SELECT id2 AS id FROM relation WHERE id1=412

Problemet med 1,2 resp. 2,1 är enkelt att lösa, det är bara att se till så att du alltid lägger det lägre av id-numren i id1 och det högre i id2.
Citera
  • 1
  • 2

Stöd Flashback

Flashback finansieras genom donationer från våra medlemmar och besökare. Det är med hjälp av dig vi kan fortsätta erbjuda en fri samhällsdebatt. Tack för ditt stöd!

Stöd Flashback