【问题标题】:How should I design the tables to store tags in a database?我应该如何设计表格以将标签存储在数据库中?
【发布时间】:2010-09-18 20:49:44
【问题描述】:
"question_id": 58640
"tags": ["polls", "fun", "quotes"]
"title": "Great programming quotes"
"question_id": 184618
"tags": ["polls", "fun", "comment"]
"title": "What is the best comment in source code you have ever encountered?"
"question_id": 3734102
"tags": ["c++", "linux", "exit-code"]
"title": "Why cant' I return bigger values from main function ?"
"question_id": 2349378
"tags": ["communication", "terminology", "vocabulary"]
"title": "New programming jargon you coined?"
"question_id": 3723817
"tags": ["open-source", "project-management", "failure", "fail"]
"title": "How to make an open source project fail"
"question_id": 3699150
"tags": ["testing", "interview-questions", "job-interview"]
"title": "Interview question please help"

这只是我使用SO API得到的一些问题的文本摘录。

为了使这个可查询,我想使用SQLite 来存储数据。

我应该如何存储 tags 列?

由于这里对 SO 的限制是五个标签,我可以使用五列 tag1、tag2 ...,但我认为可以做一些更优雅的事情。可以扩展到任意数量的标签,并且还可以处理基本查询,例如

select title from table where tag has "c++" and "boost" but not "c"

【问题讨论】:

标签: database database-design sqlite


【解决方案1】:

这是多对多的关系:问题有多个标签,标签可以出现在多个问题中。这意味着您必须创建三个表,一个用于问题,一个用于标签,一个用于这些表之间的链接。结果查询如下所示:

SELECT title FROM question
       INNER JOIN question_tag_link USING (question_id)
       INNER JOIN tag USING (tag_id)
            WHERE tag_name IN('c++', 'boost')
              AND NOT EXISTS(
           SELECT * FROM tag t1
            WHERE t1.tag_name = 'c'
              AND t1.question_id = question.question_id);

没那么简单,但我认为如果你不想被限制,这是要付出的代价。如果少于 64 个不同的标签,您可以使用 SET 字段类型,但您会失去很多灵活性(很难添加新标签)。

【讨论】:

  • 查询不会排除标有“c”的问题 - 它需要单独的and not exists (... 条件。
  • @Mark Ba​​nnister:确实!我修复了我的代码,但我不能 100% 确定 question_id = question_id 条件是否有效。您有足够的代表,请随时编辑我的帖子。
  • @gregDire:我已在 NOT EXISTS 子句中将 question 表名添加到 = question_id 字段条件和 t1 表别名 - 否则,它看起来不错。跨度>
  • @Mark Ba​​nnister:这样看起来更正确,谢谢!
【解决方案2】:

select distinct a.QuestionTitle
from
(
select q.QuestionID, QuestionTitle, TagName 
from QuestionTags as x
join Question     as q on q.QuestionID = x.QuestionID 
join Tag          as t on t.TagID      = x.TagID 
where TagName in ('c++', 'boost')
) as a
left join
(
select q.QuestionID, QuestionTitle, TagName 
from QuestionTags as x
join Question     as q on q.QuestionID = x.QuestionID 
join Tag          as t on t.TagID      = x.TagID 
where TagName = 'c'
) as b on b.QuestionID = a.QuestionID
where b.QuestionTitle is null
order by a.QuestionTitle ;

【讨论】:

  • 查询不会排除标有“c”的问题 - 它需要单独的and not exists (... 条件。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-17
  • 2015-09-12
  • 2015-03-16
  • 1970-01-01
  • 2016-06-24
  • 2011-04-23
相关资源
最近更新 更多