1
jamesxu 2017-12-18 08:39:27 +08:00 via iPhone
这是非常非常基本的 SQL,楼主一看就是根本没有学过 SQL,连基本概念都不知道,买本 SQL 必知必会看两章吧
|
2
18583826786 2017-12-18 08:44:56 +08:00 via Android
关联查询,百度下就知道了
|
3
nikoo OP |
4
lhx2008 2017-12-18 09:13:21 +08:00 via Android
这种多对多的情况,tag 再建一个表,旧表这边就是一个 doc id 对多个 tag id 就快很多了,全表扫描,数据库层那边肯定会扫的,但是有索引的话快很多
|
7
lhx2008 2017-12-18 09:25:56 +08:00 via Android 1
@nikoo 去重
tag 表就是 tagid tagname 然后标签 a b c d 就只用了 4 个 tagid 就的 tag 表变成 docid tagid 1 1 1 2 2 1 2 3 .... 第一个问题 先查 tagid=1,然后在 join doc 表取出来就可以 第二个问题,查 tagid 不等于 2 去重再 join doc 表 更快的暂时没想出来 |
8
lhx2008 2017-12-18 09:27:56 +08:00 via Android
还有就是 tagid 和 docid 要建外键,就可以自动索引了,速度快很多的
|
9
nikoo OP @lhx2008 非常感谢!实际就是这样的,即 tag 表字段是 doc_id 与 tag_id,我是为了表述方便才把 tag_id 字段写了"标签 A"这样的字串
你说的:第二个问题,查 tagid 不等于 2 去重再 join doc 表 这个怎么实现?(我 APPEND 的内容写了我做的尝试,但用 left join 似乎没法实现“不包含”某标签) |
10
clino 2017-12-18 09:37:45 +08:00
方案 1 直接改成 where tag_id!="标签 B", 这样不就是'不包含"标签 B"的 doc 记录' ?
|
11
lhx2008 2017-12-18 09:42:27 +08:00
|
12
lhx2008 2017-12-18 09:45:06 +08:00
select distinct d.* from tag_doc td join doc d where td.tagid != 2 and td.docid = d.id
刚刚打少了 |
13
NullPoint 2017-12-18 09:55:09 +08:00 1
1、select doc_id from tag where tag="标签 A" 如果有重复再去重
2、select id from doc where id not in (select doc_id from tag where tag="标签 B") |
14
nikoo OP |
15
nikoo OP @clino @lhx2008 我测试这个 SQL 是无法列出“不包含”的
mysql> select * from tag where doc_id=1; +--------+--------+ | doc_id | tag_id | +--------+--------+ | 1 | 1 | | 1 | 2 | +--------+--------+ 2 rows in set 可以确认 doc_id=1 包含 tag_id 1、2 用 td.tag_id != 2 的方法尝试列出 “不包含” tag_id 2 的 doc 记录: mysql> select distinct d.* from `tag` td join `doc` d where td.tag_id != 2 and td.doc_id = d.id; +----+-------+ | id | name | +----+-------+ | 1 | doc_1 | | 2 | doc_2 | +----+-------+ 2 rows in set 可以看到因为 doc_id=1 有两条 tag 记录,所以这条 SQL 并无法正确排除 doc_id=1 |
17
halo 2017-12-18 10:32:25 +08:00
|
18
SuperMild 2017-12-18 12:15:41 +08:00
tag 那个表的结构根本就错了。改成这种结构问题就会迎刃而解:
tag_id | tag_name | doc_ids 每一个 tag 都是独立的,有一个 doc 列表,这样不管要找有标签 A 的文章,还是不包括含 A 的文章(补集),还是“包含 A 同时不包含 B ”( B 的补集与 A 的交集)都可以轻松筛选出来。 |
20
SuperMild 2017-12-18 12:29:42 +08:00
@tomczhen 修改也不算很蛋疼,一篇文章最多十几个标签,就算 30 个吧,再多就失去标签的意义了,而标签的总量也不会太多(一般来说文章数量越多,标签总数与文章总数的比就越小)。至于这个字段的长度,的确需要评估一下。
|
22
nikoo OP @SuperMild #19 的意思是,doc_ids 这个字段包含的是文章 ID,那么普通项目一个"技术"类标签下有个几千篇文章,于是这个 doc_ids 字段要存几千个 doc_id ?
|
23
SuperMild 2017-12-18 12:39:36 +08:00
|
25
tomczhen 2017-12-18 12:52:05 +08:00
JSON 类型也避免不了数据量过大的问题,反正查找算法还有数据结构就那些。可以预见的是热门标签的 doc_ids 增加是非常迅速的,大表还能分表解决,大字段该怎么解决?
通过文章来查标签好解决,但是标签反查文章,用关系数据库真不好解决。无论采取那种结构,查询速度明显会因为标签对应文章数据量增加而变慢。 感觉要么做成延迟生效,将查询结果缓存一段时间(不然被 cc 也够呛),追求实时的高一致性技术要求很高。 |