Dostluk ilişkisini saklamak için bir ilişki veritabanı tablosu nasıl tasarlanır?


9

Web projemde arkadaşlık ilişkisini saklamak için bir tablo tasarlamak istiyorum

En azından aşağıdaki 4 koşulu karşılamalıdır:

eklenti arkadaşı isteği gönderen (ör. A TO B ise bu sütun A olur)

arkadaş ekleme isteği alan kullanıcılar (örneğin A TO B ise bu sütun B olur)

mevcut durum örn. (0 reddedilirken, 1 kabul edildi veya 2 işlenmemiş anlamına gelir

arkadaşlık ilişkimiz iki taraflı

Herhangi biriniz bu konuda deneyimli ise, herhangi bir öneri memnuniyetle karşılanır

şu anki tasarımım (şu an kötü düşünüyorum) bunlar sütunlar

frienshipId  
fromUserId  
toUserId  
status  
requestTime

Kod görünümünü kullanmanızı öneririz (metninizi vurgulayın ve ctrl-k tuşlarına basın veya her satırdan önce dört boşluk koyun) ve
DDL'nizi

Ayrıca şu tartışmaya da göz
Flo

Bir grafik veritabanı kullanın. Bunlar sadece bu koşullar için tasarlanmıştır.
Michael Green

Yanıtlar:


9

Sahip olduğunuz masaya çok benzer bir tablo oluştururdum. SQL Server veri türlerini ve sözdizimini kullanıyorum, platformunuza bağlı olarak ince ayar yapmanız gerekebilir.

CREATE TABLE FriendStatus
(FriendStatusId BIGINT PRIMARY KEY IDENTITY(1,1),
FromUserId BIGINT,
ToUserId BIGINT,
StatusId TINYINT,
SentTime DATETIME2,
ResponseTime DATETIME2);

Tablo onlarca ve yüz milyonlarca büyüdükçe tablonun endekslenmesi kritik olacaktır.


StatusId'de kümelenmiş bir dizin / birincil anahtar ne olacak?
bernd_k

Yinelenen ad sorunu düzeltildi. Kümelenmiş dizin FriendStatusId üzerinde olmalıdır. Birincil anahtar FriendStatusId veya FromUserId ve ToUserId birleşimi olabilir.
mrdenny

Birden fazla arkadaşlık isteğine izin verirseniz, PK'yi FromUserID, ToUserId, SentTime veya Kümelenmiş Dizin üzerinde isteyeceksiniz.
mrdenny

adlandırma stratejiniz daha iyi ...
Merhaba 福气 鱼

8

PostgreSQL'de:

CREATE TABLE users (
    users_id serial PRIMARY KEY,
    name text UNIQUE NOT NULL
);

CREATE TABLE friends (
    friends_id serial PRIMARY KEY,
    timestamp TIMESTAMPTZ default now(),
    user_a integer NOT NULL REFERENCES users,
    user_b integer NOT NULL REFERENCES users,
    status integer NOT NULL default 2
)

Arkadaşlıkları listelemek için bir görünüm:

CREATE VIEW friendships AS
    SELECT DISTINCT user_a, user_b FROM friends WHERE status = 1
    UNION
    SELECT DISTINCT user_b, user_a FROM friends WHERE status = 1;

Şöyle kullanabilirsiniz:

INSERT INTO users ( name ) VALUES ( 'foo' );
INSERT INTO users ( name ) VALUES ( 'bar' );
INSERT INTO users ( name ) VALUES ( 'baz' );

SELECT * FROM users;
 users_id | name 
----------+------
        1 | foo
        2 | bar
        3 | baz

INSERT INTO FRIENDS ( user_a, user_b, status ) VALUES ( 1, 2, 1 );
INSERT INTO FRIENDS ( user_a, user_b, status ) VALUES ( 2, 1, 1 );
INSERT INTO FRIENDS ( user_a, user_b, status ) VALUES ( 1, 3, 1 );

SELECT * FROM friendships ORDER BY user_a, user_b;
 user_a | user_b 
--------+--------
      1 |      2
      1 |      3
      2 |      1
      3 |      1

SELECT a.name, b.name
    FROM friendships
    JOIN users a ON a.users_id = user_a
    JOIN users b ON b.users_id = user_b
    ORDER BY a.name, b.name;
 name | name 
------+------
 bar  | foo
 baz  | foo
 foo  | bar
 foo  | baz

3

Mevcut tasarımınızın kötü olduğunu düşündüren nedir? İşte Oracle için bir oluşturma tablosu:

CREATE TABLE IVR.FRIEND (
     FRIENDID   NUMBER(7) NOT NULL 
   , FROMUSERID NUMBER(7) NOT NULL 
   , TOUSERID   NUMBER(7) NOT NULL 
   , STATUSID   NUMBER(2) NOT NULL
   , REQUESTED  DATE      NOT NULL 
   , CONSTRAINT FRIEND_PK PRIMARY KEY (FRIENDID) ENABLE 
);
CREATE SEQUENCE FRIENDIDSEQ;

Veritabanı Oracle ise, verileri belirli sorgular için gereken girişlerle sınırlandıracak dizine alınmış bir sanal sütun düşünebilirsiniz. Örneğin, DECODE (StatusId, 1, FromUserId, NULL) işlevini kullanan AcceptedFromUserId adlı sanal bir sütununuz olabilir. Dizin yalnızca AcceptedUserIds içerecektir ve bu nedenle tüm UserIds için bir dizinden daha küçük olacaktır. Reddedilen istekleri düzenli olarak temizlerseniz, PendingToUserId üzerinde dizine eklenen bir sanal sütun daha yararlı olabilir.

Bölümlemeniz olsaydı bir durum da StatusId'de tabloyu bölümlemektir.

Aynı kullanıcı arasında aynı anda birden fazla arkadaşlık isteğine ihtiyacınız yoksa, birincil anahtarınız olarak FromUserId, ToUserId ve StatusId kullanarak FriendId'den vazgeçebilirsiniz. Bu durumda, tabloyu bir İndeks Organize Tablo yapmayı da düşünmelisiniz.


-2

Şema:

CREATE TABLE users (
    users_id serial PRIMARY KEY,
    name text UNIQUE NOT NULL
);

CREATE TABLE friends (
    friends_id serial PRIMARY KEY,
    timestamp TIMESTAMPTZ default now(),
    user_a integer NOT NULL REFERENCES users,
    user_b integer NOT NULL REFERENCES users,
    status integer NOT NULL default 2
)

PHP'den:

select * 
from friends 
where user_a=$myid or user_b=$myid

Ve karşılıklılık ile ne yapmalı? (Ve friendstablo tanımı sözdizimi hatası şüphelidir.)
dezso
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.