我有两张桌子
答:
plant_ID | name.
1 | tree
2 | shrubbery
20 | notashrubbery
B:
area_ID | name | plants
1 | forrest | *needhelphere*
现在我希望该区域按特定顺序存储任意数量的植物,并且某些植物可能会出现多次:例如2,20,1,2,2,20,1
什么是存储这一系列植物的最有效方式?
请记住,我需要做到这一点,如果我执行搜索以找到植物2的区域,我不会得到例如1,20,232,12,20(带有前导0的垫?)什么会是对此的查询?
如果它有帮助,我们假设我有一个不超过99999999个不同植物的数据库。是的,这个问题与植物没有任何关系......
奖金问题 是时候离开MySQL吗?是否有更好的数据库来管理它?
答案 0 :(得分:26)
如果你要通过森林和植物进行搜索,听起来你会受益于全面的多对多关系。抛弃您的plants
列,并创建一个全新的areas_plants
表(或任何您想要调用它的表)来关联这两个表。
如果区域1有植物1和2,区域2有植物2和3,那么您的areas_plants
表将如下所示:
area_id | plant_id | sort_idx
-----------------------------
1 | 1 | 0
1 | 2 | 1
2 | 2 | 0
2 | 3 | 1
然后,您可以从任意一侧查找关系,并使用简单的JOIN从任一表中获取相关数据。不需要在LIKE条件下弄清楚它是否在列表中,等等,等等。我去过遗留数据库。没有什么好玩的。使用SQL发挥最大潜力。
答案 1 :(得分:7)
这个怎么样:
表:植物plant_ID | name
1 | tree
2 | shrubbery
20 | notashrubbery
表:区域
area_ID | name
1 | forest
table:area_plant_map
area_ID | plant_ID | sequence
1 | 1 | 0
1 | 2 | 1
1 | 20 | 2
这是标准的标准化方法(使用映射表)。
要找到所有带灌木丛的区域(植物2),请执行以下操作:
SELECT *
FROM areas
INNER JOIN area_plant_map ON areas.area_ID = area_plant_map.area_ID
WHERE plant_ID = 2
答案 2 :(得分:3)
你知道这违反了正常形式吗?
通常,会有一个areaplants表:area_ID,plant_ID,对两个表有唯一约束,对其他两个表有外键。这个“链接”表格为您提供了许多或多对一的关系。
对此的查询通常非常有效,它们使用索引而不需要解析字符串。
答案 3 :(得分:2)
您的关系属性应该是原子的,不是由列表等多个值组成。搜索它们太难了。您需要一个新的关系,将植物映射到area_ID,而area_ID /植物组合是主键。
答案 4 :(得分:2)
使用多对多关系:
CREATE TABLE plant (
plant_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255)
) ENGINE=INNODB;
CREATE TABLE area (
area_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255)
) ENGINE=INNODB;
CREATE TABLE plant_area_xref (
plant_id INT NOT NULL,
area_id INT NOT NULL,
sort_idx INT NOT NULL,
FOREIGN KEY (plant_id) REFERENCES plant(plant_id) ON DELETE CASCADE,
FOREIGN KEY (area_id) REFERENCES area(area_id) ON DELETE CASCADE,
PRIMARY KEY (plant_id, area_id, sort_idx)
) ENGINE=INNODB;
编辑:
只是回答你的红利问题:
Bonus Question Is it time to step away from MySQL? Is there a better DB to manage this?
这与MySQL无关。这只是一个糟糕的数据库设计问题。对于每个RDBMS(MySQL,Oracle,MSSQL,PostgreSQL等)中的情况,您应该使用交集表和多对多关系。
答案 5 :(得分:2)
提出此问题8年后,这里有2个想法:
1。使用json类型(link)
从MySQL 5.7.8开始,MySQL支持RFC 7159定义的本机JSON数据类型,从而可以高效地访问JSON(JavaScript对象表示法)文档中的数据。
2。使用您自己的编纂
将area_id
转换为字符串字段(varchar或text,您可以选择,考虑性能),然后可以将值表示为-21-30-2-4-20-
,然后可以使用%-2-%
进行过滤。
如果您以某种方式尝试其中的一种,那么如果您共享您的性能结果(建议的结果为1亿行),我将非常喜欢。
-
请记住,不要使用其中任何一个打破标准化的第一条规则,即every column should hold a single value