우정 관계를 저장하기 위해 관계 데이터베이스 테이블을 설계하는 방법은 무엇입니까?


9

웹 프로젝트에서 우정 관계를 저장할 테이블을 디자인하고 싶습니다

최소한 다음 4 가지 조건을 만족해야합니다.

추가 친구 요청을 보내는 사람 예 : (A TO B 인 경우이 열은 A)

친구 추가 요청을받는 사람 (예 : A TO B 인 경우이 열은 B 임)

현재 상태 eg (0은 거부, 1은 수락, 2는 처리되지 않음을 나타냄)

우리의 친구 관계는 양자입니다

이 중 하나라도 경험이 있다면, 어떤 제안이라도 환영합니다

내 현재 디자인 (지금은 나쁘다고 생각합니다)은 다음 과 같습니다.

frienshipId  
fromUserId  
toUserId  
status  
requestTime

코드 뷰 (텍스트를 강조 표시하고 ctrl-k를 누르거나 각 줄 앞에 4 개의 공백을 넣음)를 사용하고 DDL을 강조 표시하여 데이터 모델의 설계 방식 (또는 설계 방식)을
확인할 수 있습니까?

또한 토론을 확인하십시오 : stackoverflow.com/questions/10807900/…
Flo

그래프 데이터베이스를 사용하십시오. 이것들은이 상황을 위해서만 설계되었습니다.
Michael Green

답변:


9

나는 당신이 가지고있는 것과 비슷한 테이블을 만들 것입니다. SQL Server 데이터 형식과 구문을 사용하고 있으므로 플랫폼에 따라 조정해야 할 수도 있습니다.

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

테이블이 수천에서 수억으로 증가함에 따라 테이블의 인덱싱이 중요합니다.


StatusId의 클러스터 된 인덱스 / 기본 키는 어떻습니까?
bernd_k

중복 이름 문제를 해결했습니다. 클러스터형 인덱스는 FriendStatusId에 있어야합니다. 기본 키는 FriendStatusId이거나 FromUserId와 ToUserId의 조합 일 수 있습니다.
mrdenny

여러 친구 요청을 허용하는 경우 FromUserID, ToUserId, SentTime 또는 Clustered Index에서 PK를 원할 것입니다.
mrdenny

네이밍 전략이 더 좋습니다 ...
Hi 福气 鱼

8

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
)

우정을 목록으로 보려면 :

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;

다음과 같이 사용할 수 있습니다.

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

현재 디자인이 나쁘다고 생각하는 이유는 무엇입니까? 다음은 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;

데이터베이스가 Oracle 인 경우 특정 쿼리에 필요한 항목으로 데이터를 제한하는 인덱싱 된 가상 열을 고려할 수 있습니다. 예를 들어 DECODE (StatusId, 1, FromUserId, NULL) 함수를 사용하는 AcceptedFromUserId라는 가상 열이있을 수 있습니다. 인덱스는 AcceptedUserId 만 포함하므로 모든 UserId의 인덱스보다 작습니다. 거부 된 요청을 정기적으로 정리하면 PendingToUserId의 인덱싱 된 가상 열이 더 유용 할 수 있습니다.

파티셔닝을 사용하는 경우의 대안은 StatusId에서 테이블을 파티셔닝하는 것입니다.

동일한 사용자간에 동시에 여러 친구 요청이 필요하지 않으면 FromUserId, ToUserId 및 StatusId를 기본 키로 사용하여 FriendId를 포기할 수 있습니다. 이 경우 테이블을 인덱스 구성 테이블로 만드는 것도 고려해야합니다.


-2

개요:

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에서 :

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

그리고 상호 관계는 무엇입니까? (그리고 friends테이블 정의는 구문 오류가 의심됩니다.)
dezso
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.