使用Rails基于传入字符串搜索表

时间:2015-03-24 00:38:41

标签: sql ruby-on-rails ruby search

假设我们正在使用Ruby on Rails。我们有两个表:

属性:

NAME       VALUE      CODE
Size       1          a
Size       2          b
Size       3          c
Type       Tall       a
Type       Medium     b
Type       Small      c
Material   Plastic    1
Material   Metal      2
Material   Liquid     3
Option 1   Yes        y
Option 1   No         n
Option 2   Yes        y
Option 2   No         n

件:

PART     SIZE     TYPE     MATERIAL    OPTION 1     OPTION 2
A1234    1        Tall     
A1233    2        Tall
A1232    3        Tall
A1231    4        Tall
.... [there may be many parts that exhibit various attributes]
A8787                      Plastic
A8786-01                   Metal       Yes
A8786-02                   Metal       No
A8785                      Liquid
A6543                                                Yes

我想使用aa2yn之类的字符串,并根据每个字符的位置,创建一个与该特定CODE对齐的NAME和VALUE的哈希值。所以对于aa2yn,我的哈希就是 `["尺寸" => 1," Type" => " Tall","材料" => " Metal","选项1" => "是","选项2" => "否"]

然后我想使用散列中的数据查询表2。对于每个属性,仅返回包含该值或空白的PARTS。因此,对于上面给出的示例字符串,查询将返回: "A1234", "A8786-01"。此结果可以在数组中返回。根据输入字符串,将返回更多或更少的部分。 (它的实际版本将使用更大更广泛的表格,但我已按比例缩小了示例)。您可以假设字符串的顺序是预定义的,并且始终按照NAMES的顺序排列。

实现此结果的方法或方法是什么样的?

2 个答案:

答案 0 :(得分:0)

会是这样的:

select p.part 
from parts p
  left join attributes a1 on a1.name = 'Size' and p.size = a1.value 
  left join attributes a2 on a2.name = 'Type' and p.type = a2.value 
  left join attributes a3 on a3.name = 'Material' and p.material = a3.value 
  ...
where
      (a1.code is null or substring('aa2yn',1,1)=a1.code)
  and (a2.code is null or substring('aa2yn',2,1)=a2.code)
  and (a3.code is null or substring('aa2yn',3,1)=a3.code)
  ...

正如您所见,查询必须硬编码为字段名称和属性名称。或者必须在获取不同的属性名称后生成查询(问题是属性名称的正确顺序)。 substring('aa2yn',1,1)用于解释目的 - 将使用哪些参数。


要使用此类哈希,您可以在插入/更新触发器后添加到parts表,并将这些哈希计算到单独的字段中,将空属性值替换为_字符和此查询(当然它可以在客户端而不是触发器上完成:

select part
from parts
where 'aa2yn' like hash

仍然在大表上之后,这将非常缓慢,因为不会使用索引......

答案 1 :(得分:0)

Rails最适合使用规范化表格。你应该尝试规范化到第3个

create_table :sizes do |t|
  t.string :code, nil:false  #a
  t.string :value, nil:false  #1
end

create_table :types do |t|
  t.string :code, nil:false
  t.string :value, nil:false
end

.........

create_table :material_parts do |t|
  t.string :part  #A787
  t.string :value  #Plastic

end

一旦你的表被规范化,那么联接就会向前推进