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

发布于 2024-12-01 01:35:40 字数 1187 浏览 1 评论 0原文

我正在开发一个具有以下目标的项目:用户可以创建挑战并选择一个可选的对手来参加该挑战。该挑战赛会生成每日条目并跟踪这些条目的统计数据。

基本的用户和条目实体如下所示:

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

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

我遇到问题的部分是具有竞争对手概念的挑战部分。我可以看到两种方法。

// 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)
)

第一种方法的问题是引用完整性很困难,因为现在 userId 驻留在两列(ownerId 和竞争对手Id)。我必须为所有内容创建两个表(owner_entries、竞争对手_entries、owner_stats 等)才能设置外键。

第二种方法解决了这个问题,并且具有一些优点,例如允许未来有多个竞争对手。然而,我不能再用这种方法做的一件事是在单个用户而不是整个挑战表中强制挑战名称唯一性。此外,像寻找挑战的所有者这样的任务现在变得更加棘手。

挑战表的正确方法是什么?无论如何,是否可以以开发人员友好的方式设置这些表,或者我应该直接跳到类表继承并在那里管理所有者/竞争对手的概念?

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). I'd have to create two tables for everything (owner_entries, rival_entries, owner_stats, etc.) in order to set up foreign keys.

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. 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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

幸福%小乖 2024-12-08 01:35:40

我认为我的设置方法如下(使用第二种方法):

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))

这样可以轻松跟踪拥有挑战,同时提取出各个参与者。
这还允许您安全地由所有者唯一地确定挑战名称,并且 participant 中的 userId 上的外键很容易。 “对手”是所有非挑战所有者的参与者。

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. 'Rivals' are then all participants that are not the challenge owner.

海螺姑娘 2024-12-08 01:35:40

我认为第一种方法是正确的。
您可以为用户准备一张桌子,为挑战准备一张桌子。

您是否知道可以像下面这样引用一张表两次?

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

在这种情况下,您可以引用竞争对手和所有者,而无需创建新表。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文