效率问题 - 从一个字段中选择数字数据

时间:2011-02-18 18:51:58

标签: mysql search normalization

我有一对表,我需要在Table1中搜索与Table2上的相关ID匹配的数值。例如:

表1

ID | Item
1    Cat
3    Frog
9    Dog
11   Horse

表2

Category | Contains
Group 1   1
Group 2   3|9
Group 3   3|9|11

最初我认为LIKE会起作用,但如果我搜索“1”,我最终会匹配“11”。我查看了SET,但是MySQL文档声明元素的最大数量是64,而Table1中有超过200行的项目。我可以用一个字符(例如“| 1 |”)包装每个项目ID,但这似乎不是很有效。每个小组都有独特的项目(例如,同一小组中不会有两个小猫)。

我发现similar topic是我的问题,其中一个答案建议制作另一张表,但我不明白这是怎么回事。一个新表包含什么,究竟是什么?

我的另一个选择是将Contains拆分为6个单独的列,因为组中的组件永远不会超过6个,但是我不知道如何在不依赖6个OR的情况下搜索所有6个列。查询:

Category |  C1  |  C2  |  C3  |  C4 (etc)
Group 1    1      null   null   null
Group 2    3       9     null   null
Group 3    3       9      11    null

SELECT * FROM Table2 WHERE C1 = '1' OR C2 = '1' OR C3 = '1' etc.

我不确定处理此问题的最有效方法是什么。我可以使用那些有更多经验来规范这类数据的建议。谢谢。

5 个答案:

答案 0 :(得分:1)

我认为最好创建另一个表格来规范化您的数据,不过您提出的建议并不完全符合我的建议。

实际上,您建模的是table1和table2之间的多对多关系。这意味着table1中的一行可以与table2中的许多行相关联,反之亦然。

为了创建这种关系,你需要第三个表,我们现在可以调用rel_table1_table2。

rel_table1_table2将仅包含两个关联表中的主键值,在本例中似乎是table1.ID和table2.Category。

如果要将table1中的行与table2中的行相关联,则需要分别使用table1和table2中的主键值向rel_table1_table2添加一行。

示例:

INSERT INTO rel_table1_table2 (ID, Category) VALUES (1, "Group 1")

当您需要找出哪些项属于某个类别时,您只需查询您的关联表,例如:

SELECT i.Item from table1 t1 join rel_table1_table2 r on t1.ID=r.ID join table2 t2 on r.Category=t2.Category WHERE t2.Category="Group 3"

这有意义吗?

答案 1 :(得分:0)

而不是使用“喜欢”使用“REGEXP”,以便在寻找“1”时不会得到“11”

答案 2 :(得分:0)

该“新”表将为动物所属的每个类别包含一行。

create table animal(
   animal_id
  ,name
  ,primary key(animal_id)
)

create table category(
   category_id
  ,name
  ,primary key(category_id)
)

create table animal_categories(
   animal_id
  ,category_id
  ,primary key(animal_id, category_id) 
)

对于您的示例数据,animal_categories表将包含:

   category_id | animal_id  
   +-----------+------------+
   |     1     |       1    |
   |     2     |       3    |
   |     2     |       9    |
   |     3     |       3    |
   |     3     |       9    |
   |     3     |      11    |
   +-----------+------------+

答案 3 :(得分:0)

在另一个加入Table2.ContainsItem的表中中断Category

Item         Item_Category           Category
------       --------------          ---------
ID (1)----(*)ItemID                  Name
Name         CategoryID(*)-------(1) ID

现在,您的查询将如下所示:

SELECT Category.* FROM Category, Item_Category
WHERE (Item_Category.CategoryID = Category.ID)
  AND (Item_Category.ItemID IN (1, 2, 3, 11))

答案 4 :(得分:0)

您的问题似乎就是使用表2中的行的方式。在数据库中,当您发现自己在一行中使用值列表时,它应始终触发红色标记。

不是让每个类别都在表2中的单行中,如何在多行中使用相同的类别,而Contains列只存储单个值。您的示例可以更改为:

表1

ID | Item
1    Cat
3    Frog
9    Dog
11   Horse

表2

Category | Contains
Group 1    1
Group 2    3
Group 2    9
Group 3    3
Group 3    9
Group 3    11

现在,当您想要找出“组2包含哪些项目?”时,您可以编写一个查询,从中选择表2中的所有“组2”类别行。当您想要查找时,“第9项的名称是什么,您可以编写一个从表1中选择一行的查询。