Как создать таблицу базы данных отношений для хранения дружеских отношений?


9

Я хочу создать таблицу для хранения дружеских отношений в моем веб-проекте

Он должен удовлетворять как минимум следующим 4 условиям:

кто отправляет запрос на добавление в друзья, например (если A TO B, то этот столбец будет A)

кто получает запрос на добавление в друзья, например (если A TO B, то этот столбец будет B)

текущее состояние, например (0 означает отклонено, тогда как 1 означает принятый или 2 означает необработанный

наши дружеские отношения являются двусторонними

Если кто-либо из вас имеет опыт с этим, любое предложение приветствуется

мой текущий дизайн (я думаю, что плохо сейчас), как это эти столбцы

frienshipId  
fromUserId  
toUserId  
status  
requestTime

Могу ли я предложить использовать представление кода (выделите текст и нажмите ctrl-k или поставьте четыре пробела перед каждой строкой) и выделите ваш DDL, чтобы мы могли видеть, как
создается

Также проверьте обсуждение здесь: stackoverflow.com/questions/10807900/…
Flo

Используйте базу данных графа. Они предназначены именно для этих обстоятельств.
Майкл Грин

Ответы:


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.
Мрденный

Хотя, если вы разрешите несколько запросов на добавление в друзья, вам понадобится PK для FromUserID, ToUserId, SentTime или Clustered Index.
Мрденный

ваша стратегия именования лучше ...
Привет 福气 鱼

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, вы можете рассмотреть индексированный виртуальный столбец, который ограничит данные записями, необходимыми для определенных запросов. Например, у вас может быть виртуальный столбец с именем AcceptedFromUserId, который использует функцию DECODE (StatusId, 1, FromUserId, NULL). Индекс будет содержать только AcceptedUserIds и поэтому будет меньше, чем индекс для всех UserIds. Если вы регулярно очищаете отклоненные запросы, индексированный виртуальный столбец в PendingToUserId может быть более полезным.

Альтернативой, если у вас есть разделение, будет разделение таблицы по StatusId.

Если вам не нужны несколько запросов на добавление в друзья между одними и теми же пользователями одновременно, вы можете отказаться от FriendId, используя FromUserId, ToUserId и StatusId в качестве основного ключа. В этом случае вам также следует подумать о том, чтобы сделать таблицу индексированной организованной таблицей.


-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определение таблицы подозревает синтаксическую ошибку.)
Дезсо
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.