วิธีการออกแบบตารางฐานข้อมูลความสัมพันธ์เพื่อเก็บความสัมพันธ์มิตรภาพ?


9

ฉันต้องการออกแบบตารางเพื่อจัดเก็บความสัมพันธ์มิตรภาพในโครงการเว็บของฉัน

ควรตอบสนองอย่างน้อย 4 เงื่อนไขต่อไปนี้:

ผู้ที่ส่งคำขอเพิ่มเพื่อนเช่น (ถ้า A ถึง B คอลัมน์นี้จะเป็น A)

ผู้ที่ได้รับคำขอเพิ่มเพื่อนเช่น (ถ้า A ถึง B คอลัมน์นี้จะเป็น B)

สถานะปัจจุบันเช่น (0 หมายถึงถูกปฏิเสธในขณะที่ 1 หมายถึงได้รับการยอมรับหรือ 2 หมายถึงยังไม่ได้ประมวลผล

ความสัมพันธ์เพื่อนของเราคือทวิภาคี

หากคุณประสบกับข้อเสนอแนะใด ๆ ยินดี

การออกแบบปัจจุบันของฉัน (ฉันคิดว่าไม่ดีในตอนนี้) เป็นเช่นนี้ คือคอลัมน์

frienshipId  
fromUserId  
toUserId  
status  
requestTime

ฉันจะแนะนำให้ใช้มุมมองโค้ด (เน้นข้อความของคุณและกด Ctrl-k หรือใส่สี่ช่องว่างก่อนแต่ละบรรทัด) และเน้น DDL คุณเพื่อให้เราสามารถดูวิธีการรูปแบบข้อมูลของคุณได้รับการออกแบบ (หรือวิธีการที่คุณต้องการที่จะออกแบบมัน)
jcolebrand

ตรวจสอบการสนทนาได้ที่นี่: 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

แม้ว่าถ้าคุณอนุญาตให้มีคำขอเป็นเพื่อนหลายคนคุณจะต้องการ PK จาก FromUserID, ToUserId, SentTime หรือดัชนีแบบกลุ่ม
mrdenny

กลยุทธ์การตั้งชื่อของคุณดีกว่า ...
สวัสดี鱼鱼

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

schema:

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.