Sql 推特的简化版本。了解数据库中表之间的多对多关系

Sql 推特的简化版本。了解数据库中表之间的多对多关系,sql,database-design,Sql,Database Design,我正在阅读的是一种存储推特、用户、喜好等信息的关系数据库。描述并绘制了数据库方案 作为一名Android开发人员,我使用SQLite编写了我的示例。以下是我编写代码的方式: create table users (_id integer primary key, username text unique, first_name text, last_name text); create table tweets (_id integer primary key, content text, cr

我正在阅读的是一种存储推特、用户、喜好等信息的关系数据库。描述并绘制了数据库方案

作为一名Android开发人员,我使用SQLite编写了我的示例。以下是我编写代码的方式:

create table users (_id integer primary key, username text unique, first_name text, last_name text);
create table tweets (_id integer primary key, content text, created_at integer, user_id integer, foreign key(user_id) references users(_id));
create table connections (_id integer primary key, follower_id integer, followee_id integer, created_at integer, foreign key(follower_id) references users(_id), foreign key (followee_id) references users(_id));
create table favorites (_id integer primary key, user_id integer, tweet_id integer, foreign key (user_id) references users(_id), foreign key (tweet_id) references tweets(_id));
现在让我们插入一些数据

用户:

insert into users values (1, 'user1', 'Lorem', 'Ipsum');
insert into users values (2, 'user2', 'Dolor', 'Sit');
insert into users values (3, 'user3', 'Foo', 'Bar');
insert into users values (4, 'user4', 'Qwerty', 'Trewq');
一些推文:

insert into tweets values(10, '1 Tweet from user1', 1100, 1);
insert into tweets values(11, '2 Tweet from user1', 1101, 1);
insert into tweets values(12, '3 Tweet from user1', 1102, 1);
insert into tweets values(13, '4 Tweet from user1', 1103, 1);

insert into tweets values(14, '1 Tweet from user2', 1103, 2);
insert into tweets values(15, '2 Tweet from user2', 1103, 2);

insert into tweets values(16, '1 Tweet from user3', 1103, 3);
insert into tweets values(17, '2 Tweet from user3', 1103, 3);

insert into tweets values(18, '1 Tweet from user4', 1107, 4);
收藏夹(与喜欢的内容相同):

关于数据库方案有一个问题:

你认为你能支持我们的数据库设计能力吗 为给定用户显示页面,其中包含他们最近发布的 至少喜欢一次

是的,这就是为什么查询:

sqlite> select favorites._id, tweets._id as tweet_row_id, tweets.content from favorites join tweets on tweets.user_id=1 and tweets._id = favorites.tweet_id order by tweets._id desc limit 1;
_id         tweet_row_id  content
----------  ------------  ------------------
2           13            4 Tweet from user1
说明:

左侧的数据集是表收藏夹。正确的数据集是表tweets。我加入这两个数据集。然后,
tweets.user_id=1和tweets.\u id=favorites.tweet_id
作为布尔表达式为结果数据集的每一行求值。如果结果为true,则包含该行<代码>按推文排序。_iddesc用于获取最新推文(推文越大。_id越新)<代码>限制用于限制行数。如果用户多年来一直在使用我们类似Twitter的应用程序,我们将显示最新的10或20条推文


我的问题。

  • 我的数据库方案有什么问题吗?为了简单起见,我省略了
    notnull
    unique
    和其他列约束
  • 原文作者说:
  • 第一个关系是通过将用户ID粘贴到每条tweet来解决的。 这是可能的,因为每个tweet都是由一个用户创建的。 当涉及到跟踪用户和 喜欢推特。那里的关系是多对多的

    “第一关系”是用户推文

    为什么我们这里需要多对多?在我的方案中,我只使用一对多

    更新1

    很快,我发现OP——就像你在这个问题上一样——不确定
    1:n
    n:m

    我假设你的最后一句话就是你的实际问题:

    为什么我们这里需要多对多?在我的方案中,我只使用一对多

    用户tweets的关系是
    1:n

    在对象中思考

    • 用户(id、名称等)
    • 推特(id、作者(用户上的FK)、日期时间、内容等)
    like是一个对象,其自身具有单独的详细信息:

    • 比如(id、userid、tweetid、datetime等)
    为此,您需要一个映射表(称之为收藏夹)

    用户与此映射之间存在
    1:n
    -关系,推特与此映射之间存在
    1:n
    -关系。
    这两个
    1:n
    -关系一起构成
    m:n
    -关系。

    现在每个tweet都可以被很多用户喜欢,每个用户也可以喜欢很多tweet,但是一个用户不应该(可能)两次喜欢同一条tweet(唯一键,甚至两列PK?)。您可能会引入
    检查
    约束,以确保喜欢的用户和作者的用户ID不相同(不喜欢您自己的tweet)

    作为旁注: 我的数据库方案有什么问题吗

    您不应该在不命名约束的情况下创建约束

    CREATE TABLE Dummy
    (
     ID INT IDENTITY CONSTRAINT PK_Dummy PRIMARY KEY
    ,UserID INT NOT NULL CONSTRAINT FK_Dummy_UserID FOREIGN KEY REFERENCES User(id)
    ,...
    )
    
    如果这个数据库曾经安装在不同的系统上,它们将得到不同的(随机)名称,未来的升级脚本将使您陷入最深的痛苦

    更新:侧注示例 在你的评论中,你会问,最后一句话是关于什么的。。。试试这个

    CREATE DATABASE testDB;
    GO
    USE testDB;
    GO
    CREATE TABLE testTbl1(ID INT IDENTITY PRIMARY KEY,SomeValue INT UNIQUE);
    CREATE TABLE testTbl2(ID INT IDENTITY PRIMARY KEY,FKtoTbl1 INT NOT NULL FOREIGN KEY REFERENCES testTbl1(ID));
    GO
    CREATE TABLE testTbl3(ID INT IDENTITY CONSTRAINT PK_3 PRIMARY KEY,SomeValue INT CONSTRAINT UQ_3_SomeValue UNIQUE);
    CREATE TABLE testTbl4(ID INT IDENTITY CONSTRAINT PK_4 PRIMARY KEY,FKtoTbl3 INT NOT NULL CONSTRAINT FK_4_FKtoTbl3 FOREIGN KEY REFERENCES testTbl3(ID));
    
    GO
    SELECT * FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS;
    GO
    USE master;
    GO
    DROP DATABASE testDB;
    GO
    
    在结果中的列上,如下所示:

    CONSTRAINT_NAME
    ------------------------------
    PK__testTbl1__3214EC27ABEA2C0C
    UQ__testTbl1__0E5C381C04C8AF66
    PK__testTbl2__3214EC272784631C
    FK__testTbl2__FKtoTb__1367E606
    PK_3
    UQ_3_SomeValue
    PK_4
    FK_4_FKtoTbl3
    

    如果此脚本运行两次,则给定的名称将保持为您定义的名称。其他名称将获得一个随机名称,如
    PK_uuutesttbl1_uuu3214ec27abea2c0c
    。现在想象一下,您需要为几个已安装的系统创建一个升级脚本,其中必须删除或修改一个约束。如果你不知道它的名字,你会怎么做?

    如果这个数据库安装在不同的系统上,它们会变得不同(随机)名字和未来的升级脚本会让你感到最痛苦…
    我不理解这部分
    这两个1:n关系一起构成了m:n关系
    我不确定我是否理解这部分。当一个作者写很多书,而同一本书可以由几个作者写时,两个实体(由表表示)之间存在多对多关系:作者和书。但是,对于我的例子,哪些实体有多对多的关系?@ MakSimdMiRiEV来建模A<代码> M:N -关系,中间需要一个表。在您的示例中,这是带有FK to Author和FK to Book的
    AuthorBook
    。简单案例1 book 1 autor是一行。1 autor many books是每本书的一行,所有的书都有相同的autor,many autor 1 book与以前一样,但反之亦然,m:n是两者的混合体……我说的“我的例子”是指来自question@MaksimDmitriev没那么复杂:-)。。。一个表tweet,一个表用户。一个用户可以发布多条推文,每条推文只有一位作者。这与
    1:n
    有关。现在很多用户可以喜欢很多推文。这里您需要一个映射表,可以在其中看到多个组合。询问哪些用户喜欢某条推文?或者询问特定用户喜欢哪些推文?这需要
    m:n
    -关系。。。
    CONSTRAINT_NAME
    ------------------------------
    PK__testTbl1__3214EC27ABEA2C0C
    UQ__testTbl1__0E5C381C04C8AF66
    PK__testTbl2__3214EC272784631C
    FK__testTbl2__FKtoTb__1367E606
    PK_3
    UQ_3_SomeValue
    PK_4
    FK_4_FKtoTbl3