Shi*_*gga 5 sql sqlite tagging database-design
如何将项目的标签存储在数据库中无忧?
每个项目都带有多个标签。我已经阅读了一些有效的解决方法:
但我认为对此有更好的解决方案。为什么我们不能简单地将标签作为每个项目的长字符串包含在内?
Table : Brand_Shops
Columns : brand_id, brand_name, content, tags
Run Code Online (Sandbox Code Playgroud)
范例:
1 || Nike || shoes bags sports football soccer t-shirts track-pants
2 || GAP || wallets t-shirts jeans shoes perfumes
Run Code Online (Sandbox Code Playgroud)
这没有原子性,但完全适合标记的目的。如果必须添加新品牌,只需将新标签与其一起添加。因此,获取它也将非常容易。我不明白为什么这不是一个有效的解决方案。
我不明白为什么这不是一个有效的解决方案。
它效率低下,因为您必须为每个查询检索并中断/搜索该字符串。
当您执行类似的操作(如链接中所述)时Three tables (one for storing all items, one for all tags, and one for the relation between the two),您可以使用关系数据库的真正强大功能,即索引。
不再将每个字符串分解为一个标签或一组标签......这已经完成了;你只得到你想要的。因此,如果您正在搜索“鞋子”,那么它会直接到达那里(使用索引可能是 log n 或更快)并返回 Nike 和 GAP。无论您有多少个标签,无论您有多少家公司,它都会执行此操作。
使用 3 表系统,您可以预先完成所有艰苦的工作,然后只进行查找。
如果您打算在本地或有限数量的用户中运行此解决方案,您的解决方案可能会很好。编码也更容易。
一旦您的查询开始花费几秒钟以上,您可能需要更新您的标记系统。如果您这样做,请单独编写搜索代码,以防您需要将其撕掉。
评论中的问题:
你能举一个用原子性规范化的 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
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1382 次 |
| 最近记录: |