1
l1nyanm1ng 2020-05-12 18:07:59 +08:00 1
百度 ❌
谷歌 ❌ 打开 V2EX 来和问问题(实则借机开始划水 ✔️ |
2
wangkun025 2020-05-12 18:11:16 +08:00
people
relationships person_relationships |
3
mebtte OP @l1nyanm1ng 猜对了
|
4
mebtte OP @wangkun025 要支持正反向查询, 比如爷爷的孙子们 /孙子的爷爷
|
5
xupefei 2020-05-12 18:14:36 +08:00 via iPhone 1
你需要的应该是 RDF 。
|
6
annielong 2020-05-12 18:14:54 +08:00
基本的都是递归,id,name,upid
|
7
2exploring 2020-05-12 18:16:27 +08:00
一张人表,一张父子关系表,不就结了
|
8
wangkun025 2020-05-12 18:17:22 +08:00 1
@mebtte 加需求要加钱的
|
9
superrichman 2020-05-12 18:21:33 +08:00 via iPhone
可以参考《 sql antipatterns 》这本书第三章来设计存储和读取树形结构。
|
10
mebtte OP @2exploring 隔了好几代不好查询
|
11
yangliulnn 2020-05-12 18:47:04 +08:00 via Android
左右值了解一下
|
12
egfegdfr 2020-05-12 19:01:22 +08:00
在 id,name,upid 的基础上在加一个 path 的字段、用来记录这个当前节点的所有父节点。
|
13
hantsy 2020-05-12 19:03:11 +08:00
这样 100%用 Neo4j 方便啦。
|
14
hteen 2020-05-12 19:03:15 +08:00 via iPhone
闭包表
|
15
FFFire 2020-05-12 20:20:31 +08:00
建议使用 Excel
|
16
k9990009 2020-05-13 00:07:44 +08:00 via Android
不就是树嘛,除了父 ID,再加上父路径 1,3,5,…… 想怎么查都阔以
|
17
Keyes 2020-05-13 00:11:35 +08:00 via iPhone
爸爸辈太多的话,查孙子会比较吃性能,我只想到了买个更好硬件的 server
然后:图数据库就干这个事的 |
18
izoabr 2020-05-13 00:16:57 +08:00
我觉得 JSON 也挺合适的,有结构且明文
|
19
Solarest 2020-05-13 00:51:40 +08:00 via Android
参考图数据库的设计方式,分表存:实体 a 、实体 a 和 b 的关系、实体 b 。
|
20
tulongtou 2020-05-13 01:55:38 +08:00 via iPhone 3
感觉不用设计想怎么存怎嘛存,族谱能有多少人?几百几千?哪怕上万了,也不需要设计啊,这个数量级怎么存都没毛病
|
21
ericgui 2020-05-13 02:19:55 +08:00
族谱就是一个 tree
你考虑一下 |
22
lights 2020-05-13 02:43:14 +08:00
如果频繁间隔很多代际查询的话,建议上图数据库,不推荐 OrientDB (我被它坑得死去活来)
可以考虑 Mysql 层面模仿图数据库的存储结构(如 19 楼所说) 另外因为“关系数据”内容量很小(甚至不会超过 50MB ),可以每次将关系数据从 Mysql 中缓存到内存,然后每次查询直接在内存中用图算法算,再将获取到的关系结果到 MySQL 中查询具体的数据(有现成的图查询库可以找找看) |
23
lumotian 2020-05-13 04:46:17 +08:00
mongodb
|
24
levelworm 2020-05-13 06:25:39 +08:00 via Android
最高多少代,直接所有数据 dump 出来存储。。。
|
25
ebony0319 2020-05-13 08:31:50 +08:00 via Android
多一列:祖先是谁。这样方便认祖归宗(查并集)。比如第五代与十五代,只要祖宗相同说明是同族。
|
26
fxxwor99LVHTing 2020-05-13 08:52:05 +08:00
如果数据量不大,那么直接就一棵树就行,
表结构,一张表也行吧, id,parentId 查询的时候一次性把同族的所有数据拿出来,然后根据 parentId 把各个节点链接成一棵树,同时把节点在 map 里面根据 id 存一份,这样查询就很快了, entity 里面两个属性 parentNode, 和 childrenNodes,父节点只有一个,但是子节点可能有多个 |
27
wei193 2020-05-13 08:56:53 +08:00 via Android
用两个字段,一个字段记录代数,一个字段记录关系树,比如 1/2/4/8 。那么你可以用 Like 1/2/% AND 4 代 来找他的孙子。当年我是这样做的,有更多需要可以啊。
|
29
tankren 2020-05-13 09:05:14 +08:00
纸质版的族谱看起来才有意思
|
30
encro 2020-05-13 09:19:00 +08:00
非常有意思的题目,
昨天想了很久, 觉得没有很好答案。 今天忽然想到的: 族谱有一个特点就是写入少, 所以可以建立一个缓存表, 缓存关系链。 比如: people 表: id, name, father_id, mother_id, order, relation 表: id, from_id, to_id, type 这里 people 是常规的做法就好, people 新增和修改的时候,维护好 relation 表上下的关系。 这样查询的时候自动根据 relation 以及 type 就能一次查到所有关联关系。 |
31
12tall 2020-05-13 09:19:33 +08:00
数据部太多的话,有一种想法,数据表结构
id, name, p_id 然后将查询结果保存到哈希表常驻内存,也可以再构造一个树,个人觉得比较适合不常变的数据 反模式里面的闭包表也用过,就是一个自己关于自己的中间表,增删改时会相对复杂些,如果存很多份族谱的,这种应该比较合适 |
32
encro 2020-05-13 09:24:13 +08:00
people 表可以扩展一下:
id, family_id, // 族号 name, father_id, mother_id, order, // 第几个孩子 level, // 第几代 relation 表也可以扩展下: id, from_id, to_id, type, level, // 相对层级 可以为负数 |
33
xuanbg 2020-05-13 09:25:42 +08:00
数据结构好说,麻烦的是关系。假设曹丞相收了吕布女儿为妾,吕布认曹丞相为父……
你说这曹氏族谱该怎么写 |
34
dog82 2020-05-13 09:30:49 +08:00
简单的就 id parent_id 递归查询就行,mysql postgre oracle 都行
|
35
encro 2020-05-13 09:32:04 +08:00
@wangkun025
才发现 2 楼就有利用关系表的意思了,不过当时没有看清楚。 前面有说到用 path 的办法,如果层级不多是可以的,层级多了,索引太长吧,如果真追溯到祖宗 5 代以上。 其实前期数据不多,可以不要 relation 表,有 family_id,level 就可以了,根据 family_id 和 level 就可以查出上下几代的数据,用程序运算也很快的。 |
37
gamexg 2020-05-13 09:34:54 +08:00
我想起了一个族谱软件作者的吐槽
客户反馈族谱软件挂了,作者检查后发现,爸爸的妻子是女儿(记不清了,类似的关系),死循环了。 不知道你这里是否需要考虑这种少见的关系。 |
38
laminux29 2020-05-13 09:36:41 +08:00
论各种数据结构如何转化为数据库的表与关系。
|
39
encro 2020-05-13 09:37:27 +08:00 1
create index family_level(family_id,level);
select * from people where family_id=3 and level between current_level-3,current_level+3; 这样高性能将上下三代查出来了。 这样看来不要 relation 表也是可以的。 |
41
ylsc633 2020-05-13 10:13:20 +08:00
我也考虑过 做一个族谱! 因为我爸正在把 老祖宗传下来的族谱进行 图形化!
我再配合一个网站 就完美了! 族谱除了简单的 树形结构! 其实还有 其他的情况! 比如 某某 过继 给 某某! 那么他就会有两个父级! 甚至多个! 这种情况在族谱里经常出现! 还是这种情况 年轻时过继给某某! 去世后 迁回, 还属于出生的那一支.... 另外 图形化的 我参考过 那个 全历史 感觉不错! 可惜不会写 |
43
hcymk2 2020-05-13 10:24:42 +08:00
软件真的好难做啊 coolshell.cn/articles/4811.html
|
45
x66 2020-05-13 10:56:04 +08:00
左右值
|
46
legiorange 2020-05-13 12:36:17 +08:00
@ylsc633 考虑过,这个时候关系本身的冗余设计体现了真正的用途。和 44 楼说的一样,但维持原来的父关系是必要的(溯源),再增加一个关联关系字段似乎是稳妥的方案。
比如 两个父,一个母,异父同母的孩子 X2,看似就可以妥善的解决了? |
47
Baelish725 2020-05-13 12:46:20 +08:00
这种用图数据库比较方便,不用考虑设计复杂的数据结构,图数据库就是为了解决这种社交关系、环状、树状的关系设计的
|
49
justfindu 2020-05-13 13:52:14 +08:00
左右值树形结构就行了
|
50
starcraft 2020-05-13 14:27:13 +08:00
邻接表就行。别去存什么完整路径,顶多加个 level,数据少的可怜的话,连这个都不用,反正直接递归就完事了。注意个环检测。尽管 mysql 是 8 加入的 cte,但老版本也能自己模拟,就是性能肯定比不上原生支持。
|
52
guolaopi 2020-05-13 17:55:19 +08:00
@encro #39
使用 level 真的很巧妙,这样的话要找任何一代的上下 X 代,就从他的 level +- X 即可。 太棒了思路! 我还在想怎么找爷爷的爷爷辈,这样只要找到爷爷的 id,然后 level+3 即可,无需递归。 但是存在一个缺陷,祖先元素( root )发生变化后所有的 level 是不是都要变化? 假设现在祖先是 A,最顶级的元素,按这个设计 A 的 level 应该是 0 。 假若通过别的某些途径证明 A 上面还有 AAA 是 A 的父级,那么此时 AAA 就应该是族谱里的祖先, 如果是这样的话 level 应该怎么搞,-1 吗? |
53
encro 2020-05-13 18:48:37 +08:00
结合大家说的变更问题,那么需要将关系抽离出来:
people 表: id name 姓名 relation 表: id family_id 族号 一个用户可能存在多个族谱中,比如外嫁后进入其他族谱 people_id 用户编号 level 代系 relate_people_id 关联人, type 关系:如丈夫,妻子,儿子,孙子,情人 order 第几个孩子,第几任妻子 alter table relation create index family_level(family_id,level); select * from relation where family_id=3 and level between current_level-3,current_level+3; 这样高性能将上下三代查出来了。 这两个表记录基本不用改(除非录错了),任何时候都是增加记录即可,所以维护也非常简单。 界面展示上,查询出上下几代,然后名字作为主要展示标签,关系用连线展示,关系和人是多对多,完美解决关系混乱的问题。 这里一个人可能即是二代也是三代,是两个身份,所以算两个点。 不知道怎么 v2 贴图,参考图我先放我自己 blog 上了。 族谱的数据设计 https://c4ys.com/archives/2141 |
55
encro 2020-05-13 18:54:09 +08:00
level 代表是族谱里面的第几代。
如果发现了新的祖先,然么当然自己代数要加一。 比如李渊原来 level 是 1 代,然后认了老子做祖宗,那么他就不 1 代了,老子是 1 代。 |
56
Zien 2020-05-13 19:10:51 +08:00 via Android
parent_id 和 person_id 级联(假定只是父系族谱
|
57
realpg 2020-05-14 00:25:44 +08:00
族谱这种除非录入错误,不会 update 的数据库
基础表按 relation 结构 然后针对热度超高冗余度就好了…… 反正你族谱再大也不会超过十万人吧 在数据库这都是小 case 别说爷爷,把四五代数据都生成冗余类视图的表都没啥事儿 |