2013-01-25 102 views
2

对于每个产品的产品筛选方案,我有以下四个表。 每个产品可以有多个属性,可以有多个值。Mysql - 按属性筛选产品

如何建立SQLQuery对一个用户请求多个属性进行搜索就像

CPU: >1000 
Price <700 

我最后jQuery的是腐败的性能:

SELECT 
    attributes_vals.*, handys.* 
FROM 
    handys join handy_has_vals on handys.id=handy_has_vals.handy_id 
    join attributes_vals on attributes_vals.id=handy_has_vals.val_id 
WHERE 
    `attributes_vals`.`attr_id`=374 
    AND(`attributes_vals`.`vals` >=1000 AND `attributes_vals`.`vals` >=1500) 
    OR `attributes_vals`.`attr_id`=68 AND(`attributes_vals`.`vals`='YES') 
    OR `attributes_vals`.`attr_id`=11 AND(`attributes_vals`.`vals` LIKE 'GPRS%') 

小提琴&测试:http://SQLFiddle.com/#!2/bba51/2

这里是表格

handys 
id | name | modell 
1 | Samsung | galaxy A 
2 | Samsung | galaxy B 
3 | Samsung | galaxy C 
4 | Samsung | galaxy D 

handy_has_vals 
handy_id | attr_id | val_id 
1   | 1  | 1 
1   | 2  | 3 
1   | 3  | 6 
1   | 4  | 11 
2   | 1  | 2 
2   | 2  | 4 
2   | 3  | 7 
2   | 4  | 10 
3   | 1  | 1 
3   | 2  | 5 
3   | 3  | 8 
3   | 4  | 10 
4   | 1  | 2 
4   | 2  | 3 
4   | 3  | 9 
4   | 4  | 11 

attributes_vals 
id | attr_id | vals 
1 | 1  | 'YES' 
2 | 1  | 'No' 
3 | 2  | '1200' 
4 | 2  | '1000' 
5 | 2  | '1500' 
6 | 3  | '300' 
7 | 3  | '350' 
8 | 3  | '800' 
9 | 3  | '550' 
10 | 4  | 'YES' 
11 | 4  | 'No' 

attributes 
id | attr_name 
1 | 'GPS' 
2 | 'CPU' 
3 | 'Price' 
4 | 'WLAN' 
+0

似乎EXISTS子句将是最简单的解决方案。 – Bulat

回答

1

应该类似于:

SELECT * FROM handys h 
INNER JOIN handy_has_vals hv ON h.id = hv.handy_id 
INNER JOIN attributes a ON hv.attr_id = a.id 
INNER JOIN attributes_vals av ON av.attr_id = a.id 
WHERE (a.attr_name = 'CPU' AND av.vals > '1000') or ( a.attr_name = 'Price' AND av.vals < '700') 

而且,为了使由数字,而不是字符串比较:

SELECT * FROM handys h 
INNER JOIN handy_has_vals hv ON h.id = hv.handy_id 
INNER JOIN attributes a ON hv.attr_id = a.id 
INNER JOIN attributes_vals av ON av.attr_id = a.id 
WHERE (a.attr_name = 'CPU' AND cast(av.vals AS UNSIGNED) > '1000') or ( a.attr_name = 'Price' AND cast(av.vals AS UNSIGNED) < '700') 

虽然,中CAST您的where子句中使用,保证您进行全表扫描,如果您有足够的记录,将会大幅降低性能。

+0

我已经尝试过您的SQLquery http://sqlfiddle.com/#!2/bba51/34 但它给了我所有产品 – dazzafact

0

尝试此查询

SELECT 
    attributes_vals . *, handys . * 
from 
    handys 
     join 
    handy_has_vals ON handys.id = handy_has_vals.handy_id 
     join 
    attributes_vals ON attributes_vals.id = handy_has_vals.val_id 
WHERE 
    attributes_vals.attr_id IN (68, 11, 374) 
    AND ((attributes_vals.vals >= 1000 AND attributes_vals.vals >= 1500) 
      OR attributes_vals.vals = 'YES' OR attributes_vals.vals LIKE 'GPRS%') 
+0

但是有多个值。您的语句在attr_ids之间没有区别。 – dazzafact

0

尝试这样

SELECT 
    attributes_vals . *, handys . * 
from 
    handys 
     join 
    handy_has_vals ON handys.id = handy_has_vals.handy_id 
     join 
    attributes_vals ON attributes_vals.id = handy_has_vals.val_id 
WHERE 
    ((attributes_vals.vals >= 1000 AND attributes_vals.vals >= 1500) 
      OR attributes_vals.vals = 'YES' OR attributes_vals.vals LIKE 'GPRS%') 
+0

没有主键! – dazzafact