标签或标签的数据库设计

时间:2018-06-11 08:15:20

标签: sql sqlite database-design tagging

如何存储在数据库中的项目标签无忧无虑?

每个项目都有多个标签。我已经以有效的方式阅读了几个答案:

  1. What is the most efficient way to store tags in a database?
  2. Recommended SQL database design for tags or tagging
  3. 但我认为有一个更好的解决方案。为什么我们不能只将标签包含为每个项目的长字符串?

     Table : Brand_Shops
     Columns : brand_id, brand_name, content, tags
    

    示例:

    1 || Nike ||  shoes bags sports football soccer t-shirts track-pants
    2 ||  GAP || wallets t-shirts jeans shoes perfumes
    

    这没有 atomicity ,但完全符合标记的目的。如果必须添加新品牌,可以简单地添加新标签。因此,获取它也很容易。我不明白为什么这不是一个有效的解决方案。

1 个答案:

答案 0 :(得分:2)

  

我不明白为什么这不是一个有效的解决方案。

效率低下,因为您必须为每个查询检索并中断/搜索该字符串。

当您执行类似(如链接中所述)Three tables (one for storing all items, one for all tags, and one for the relation between the two)之类的操作时,您可以使用关系数据库的真正功能,索引

而不是将每个字符串分成标签或一组标签......已经完成了;你得到你想要的那些。所以,如果你正在寻找"鞋子"然后它直接在那里(使用索引可能是log n或更快)并返回Nike和GAP。无论您拥有多少公司,无论您有多少公司,它都会这样做。

使用3-table系统,您可以预先完成所有艰苦工作,然后进行查找。

如果您打算在本地或使用有限数量的用户运行此解决方案,那么您的解决方案可能没问题。编码也更容易 一旦您的查询开始花费超过几秒钟,您可能想要更新您的标记系统。如果您这样做,请单独编写搜索代码,以防您需要将其删除。

评论提问:

  

您能举例说明使用标准化的3表系统吗?   原子

不确定。
你基本上要求第三范式,这是我通常的目标。 (我承认我经常不做3NF因为我优化;例如用邮件存储邮政编码 - 如果你不在学校,这是一个更好的选择)

--Sample SQL stackoverflow.com/questions/50793168/database-design-for-tags-or-tagging/50818392
IF NOT EXISTS (SELECT * FROM sys.schemas WHERE name = N'ChrisC') 
BEGIN
 EXEC sys.sp_executesql N'CREATE SCHEMA [ChrisC] AUTHORIZATION [dbo]'
 IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[ChrisC].[Brands]') AND type in (N'U'))
     AND NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[ChrisC].[BrandTags]') AND type in (N'U'))
     AND NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[ChrisC].[Tags]') AND type in (N'U'))
 BEGIN
  CREATE TABLE [ChrisC].[Brands]([pkBrand] [int] IDENTITY(101,1) NOT NULL,[Name] [varchar](40) NULL) ON [PRIMARY]
  INSERT INTO [ChrisC].[Brands]([Name])VALUES('Nike'),('GAP')
  CREATE TABLE [ChrisC].[BrandTags]([pk] [int] IDENTITY(1,1) NOT NULL,[Brand] [int] NULL,[Tag] [int] NULL) ON [PRIMARY]
  INSERT INTO [ChrisC].[BrandTags]([Brand],[Tag])VALUES
    (101,201),(101,202),(101,203),(101,204),(101,205),(101,206),(101,207),
    (102,208),(102,209),(102,203),(102,207),(102,210)
  CREATE TABLE [ChrisC].[Tags]([pkTag] [int] IDENTITY(201,1) NOT NULL,[Tag] [varchar](40) NULL) ON [PRIMARY]
  INSERT INTO [ChrisC].[Tags]([Tag])VALUES
    ('bags'),('football'),('shoes'),('soccer'),('sports'),('track-pants'),('t-shirts'),('jeans'),('perfumes'),('wallets')
  SELECT b.[Name], t.Tag 
  FROM chrisc.Brands b 
  LEFT JOIN chrisc.BrandTags bt ON pkBrand = Brand
  LEFT JOIN chrisc.Tags t ON bt.Tag = t.pkTag
  WHERE b.[Name] = 'Nike'
  -- Stop execution here to see the tables with data
  DROP TABLE [ChrisC].[Brands]
  DROP TABLE [ChrisC].[BrandTags]
  DROP TABLE [ChrisC].[Tags]
 END
 IF  EXISTS (SELECT * FROM sys.schemas WHERE name = N'ChrisC') DROP SCHEMA [ChrisC]
END