Làm thế nào để thiết kế một bảng cơ sở dữ liệu mối quan hệ để lưu trữ mối quan hệ hữu nghị?


9

Tôi muốn thiết kế một bảng để lưu trữ mối quan hệ hữu nghị trong dự án web của mình

Nó sẽ đáp ứng ít nhất 4 điều kiện sau đây:

người gửi yêu cầu kết bạn, ví dụ: (nếu A ĐẾN B thì cột này sẽ là A)

người nhận được yêu cầu kết bạn, ví dụ: (nếu A ĐẾN B thì cột này sẽ là B)

trạng thái hiện tại, ví dụ (0 biểu thị bị từ chối trong khi 1 biểu thị được chấp nhận hoặc 2 biểu thị chưa được xử lý

mối quan hệ bạn bè của chúng tôi là song phương

Nếu bất kỳ ai trong số bạn có kinh nghiệm với điều này, bất kỳ đề nghị nào đều được hoan nghênh

thiết kế hiện tại của tôi (tôi nghĩ là xấu ngay bây giờ) giống như đây là những cột

frienshipId  
fromUserId  
toUserId  
status  
requestTime

Tôi có thể đề xuất sử dụng chế độ xem mã (tô sáng văn bản của bạn và nhấn ctrl-k hoặc đặt bốn khoảng trắng trước mỗi dòng) và tô sáng DDL của bạn để chúng tôi có thể xem mô hình dữ liệu của bạn được thiết kế như thế nào (hoặc cách bạn muốn thiết kế nó)
jcolebrand

Đồng thời kiểm tra cuộc thảo luận tại đây: stackoverflow.com/questions/10807900/ từ
Flo

Sử dụng cơ sở dữ liệu đồ thị. Chúng được thiết kế cho hoàn cảnh này.
Michael Green

Câu trả lời:


9

Tôi sẽ tạo một bảng rất giống với bảng mà bạn có. Tôi đang sử dụng kiểu dữ liệu và cú pháp của SQL Server, bạn có thể cần phải điều chỉnh tùy thuộc vào nền tảng của mình.

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

Lập chỉ mục của bảng sẽ rất quan trọng khi bảng tăng lên hàng chục và hàng trăm triệu.


Điều gì về một chỉ mục cụm / khóa chính trên StatusId?
bernd_k

Đã sửa lỗi trùng lặp tên. Chỉ mục Clustered phải có trên FriendStatusId. Khóa chính có thể là FriendStatusId hoặc kết hợp FromUserId và ToUserId.
mrdenny

Mặc dù nếu bạn cho phép nhiều yêu cầu kết bạn, bạn sẽ muốn PK trên FromUserID, ToUserId, SentTime hoặc Clustered Index.
mrdenny

chiến lược đặt tên của bạn tốt hơn ...
Xin chào 福气 鱼

8

Trên PostgreSQL:

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
)

Để liệt kê tình bạn, một quan điể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;

Bạn có thể sử dụng nó như vậy:

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

Điều gì làm cho bạn nghĩ rằng thiết kế hiện tại của bạn là xấu? Đây là bảng tạo cho Oracle:

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;

Nếu cơ sở dữ liệu là Oracle, bạn có thể muốn xem xét một cột ảo được lập chỉ mục sẽ giới hạn dữ liệu cho các mục cần thiết cho các truy vấn cụ thể. Ví dụ: bạn có thể có một cột ảo có tên là AcceptedFromUserId sử dụng hàm DECODE (StatusId, 1, FromUserId, NULL). Chỉ mục sẽ chỉ chứa AcceptedUserIds và do đó sẽ nhỏ hơn chỉ mục cho tất cả UserIds. Nếu bạn thường xuyên dọn dẹp các yêu cầu bị từ chối, một cột ảo được lập chỉ mục trên PendingToUserId có thể hữu ích hơn.

Một cách khác nếu bạn có phân vùng sẽ là phân vùng bảng trên StatusId.

Nếu bạn không cần nhiều yêu cầu kết bạn giữa cùng một người dùng thì bạn có thể từ bỏ FriendId bằng FromUserId, ToUserId và StatusId làm khóa chính của bạn. Trong trường hợp này, bạn cũng nên xem xét việc tạo bảng thành Bảng tổ chức chỉ mục.


-2

Lược đồ:

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
)

Từ PHP:

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

Và phải làm gì với sự tương hỗ? (Và friendsđịnh nghĩa bảng là nghi ngờ cho lỗi cú pháp.)
dezso
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.