简体   繁体   English

SQL一对多表与多个一对一关系

[英]SQL One-to-Many Table vs. multiple one-to-one relationships

I'm working on a project with the following objective: A User can create a Challenge and select an optional Rival to take part of this challenge. 我正在一个具有以下目标的项目上:用户可以创建一个挑战并选择一个可选的竞争对手来参与此挑战。 The Challenge generates Daily entries and will track stats on these. 挑战生成每日条目,并将跟踪这些条目的统计信息。

The basic User and Entry entities look like this: 基本的用户和条目实体如下所示:

CREATE TABLE users (
    id (INT),
    PRIMARY KEY (id)
);

CREATE TABLE entries (
    challengeId INT,
    userId INT,
    entryDate DATE,
    entryData VARCHAR,
    PRIMARY KEY (challengeId, userId, entryDate)
)

The piece I'm having trouble with is the Challenge piece with the Rival concept. 我遇到的问题是带有“竞争”概念的“挑战”部分。 I can see two approaches. 我可以看到两种方法。

// Hard code the concept of a Challenge Owner and Rival:
CREATE TABLE challenges (
    id INT,
    name VARCHAR,
    ownerId INT,
    rivalId INT NULL,
    PRIMARY KEY (id),
    UNIQUE KEY (ownerId, name)
);

// Create Many-to-one relationship.
CREATE TABLE challenges (
    id INT,
    name VARCHAR,
    PRIMARY KEY (id),
    UNIQUE KEY (name)
)
CREATE TABLE participant (
    challengeId INT,
    userId INT,
    isOwner BIT,
    PRIMARY KEY (challengeId, userId)
)

The problem with the first approach is that referential integrity is tough since now there are two columns where userIds reside (ownerId and rivalId). 第一种方法的问题是引用完整性很困难,因为现在有两列userId驻留在其中(ownerId和竞争对手ID)。 I'd have to create two tables for everything (owner_entries, rival_entries, owner_stats, etc.) in order to set up foreign keys. 我必须为所有内容(owner_entries,竞争对手_entries,owner_stats等)创建两个表,以便设置外键。

The second approach solves this and has some advantages like allowing multiple rivals in the future. 第二种方法可以解决此问题,并具有一些优点,例如将来允许多个竞争对手。 However, one thing I can't do anymore with that approach is enforce Challenge name uniqueness across a single user instead of the whole Challenge table. 但是,使用该方法无法做的一件事是在单个用户而不是整个Challenge表中强制执行Challenge名称唯一性。 Additionally, tasks like finding a Challenge's owner is now trickier. 此外,诸如查找挑战的所有者之类的任务现在变得更加棘手。

What's the right approach to the Challenges table? 什么是挑战表的正确方法? Is there anyway to set up these tables in a developer friendly manner or should I just jump all the way to Class Table Inheritance and manage the concept of Owner/Rivals there? 无论如何,有没有以对开发人员友好的方式设置这些表,还是我应该直接跳到类表继承并在那里管理所有者/竞争对手的概念?

I think the way I would set this up is as follows (using the second approach): 我认为我的设置方法如下(使用第二种方法):

CREATE TABLE challenges (id INT, 
                         name VARCHAR, 
                         owner_id INT, 
                         PRIMARY KEY (id),
                         UNIQUE KEY (name, owner_id))

CREATE TABLE participant (challengeId INT,
                          userId INT, 
                          PRIMARY KEY (challengeId, userId))

This allows easy tracking of who owns the challenge, yet extracts out the individual participants. 这样可以轻松跟踪是挑战者,同时又可以提取出各个参与者。
This would also allow you to unique the challenge name by the owner safely, and foreign keys on the userId in participant are easy. 这也将允许您安全地由所有者唯一地设置质询名称,并且participantuserId上的外键很容易。 'Rivals' are then all participants that are not the challenge owner. 因此,“竞争对手”是不是挑战所有者的所有参与者。

I treat the first approach the right one. 我认为第一种方法是正确的。 You could have one table for users and one for challenges. 您可以为用户提供一张桌子,为挑战提供一张桌子。

Are you aware that you can reference one table twice like below? 您是否知道可以像下面一样两次引用一个表?

SELECT * FROM CHALLENGES 
INNER JOIN USERS AS OWNERS ON OWNERS.ID = CHALLENGES.OWNERID
INNER JOIN USERS AS RIVALS ON RIVALS.ID = CHALLENGES.RIVALID

In this case you can reference both rivals and owners without creating new tables. 在这种情况下,您可以引用竞争对手和所有者,而无需创建新表。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM