数据库设计启用多个标签,如Stackoverflow?

Sri*_*apu 3 mysql database database-design junction-table database-schema

我有以下表格.

文章
a_id INT主要唯一
名称 VARCHAR
描述 VARCHAR
c_id INT

类别
ID INT
cat_name VARCHAR

现在我只是使用

SELECT a_id,name,Description,cat_name FROM Articles LEFT JOIN Category ON Articles.a_id=Category.id WHERE c_id={$id}

这给了我所有属于某个类别的文章以及类别名称.
每篇文章只有一个类别.

我以类似的方式使用子类别(我有另一个名为sub_cat的表).
但是每篇文章都没有必要的子类别.它可能属于多个类别.

我现在想到标记一个包含多个类别的文章就像stackoverflow中的问题被标记一样(例如:有多个标签,如PHP,MYSQL,SQL等).

以后我必须显示(过滤)所有文章与某些标签(例如:标记为php,php + MySQL),我还必须显示标签以及文章名称,描述.
谁能帮我重新设计数据库?(我在后端使用php + MySQL)

RBa*_*ung 7

创建一个新表:

CREATE TABLE ArticleCategories(
    A_ID INT,
    C_ID INT,
    Constraint PK_ArticleCategories Primary Key (Article_ID, Category_ID)
)
Run Code Online (Sandbox Code Playgroud)

(这是SQL服务器语法,对于MySQL可能略有不同)

这称为" 连接表 "或" 映射表 ",它是您在SQL中表达多对多关系的方式.因此,每当您想要将一个类别添加到文章时,只需INSERT在该表中添加一行,其中包含文章和类别的ID.

例如,您可以像这样初始化它:

INSERT Into ArticleCategories(A_ID,C_ID)
    SELECT A_ID,C_ID From Articles
Run Code Online (Sandbox Code Playgroud)

现在您可以c_id从文章表中删除.

要获取单个文章的所有类别,您可以使用如下查询:

SELECT a_id,name,Description,cat_name 
FROM Articles 
LEFT JOIN  ArticleCategories ON Articles.a_id=ArticleCategories.a_id 
INNER JOIN Category ON ArticleCategories.c_id=Category.id 
WHERE Articles.a_id={$a_id}
Run Code Online (Sandbox Code Playgroud)

或者,要返回具有LIKE某个字符串类别的所有文章:

SELECT a_id,name,Description
FROM Articles 
WHERE EXISTS(   Select * 
                From ArticleCategories 
                INNER JOIN Category ON ArticleCategories.c_id=Category.id 
                WHERE Articles.a_id=ArticleCategories.a_id 
                  AND Category.cat_name LIKE '%'+{$match}+'%'
             )
Run Code Online (Sandbox Code Playgroud)

(您可能必须调整最后一行,因为我不确定如何通过MySQL + PHP传递字符串参数.)

  • +1.也许包含FK约束也是一个好主意? (2认同)
  • @Shrikanth这很好用,这是在Relational/SQL数据库中执行此操作的唯一正确方法.我向你保证,你想做的任何其他方式都会在98%的时间里表现得更差,并且编码和维持99.9%的时间会更糟.这就是SQL/Relational数据库*假设*工作的方式,所有SQL产品都是为此而构建的. (2认同)