当前位置:  开发笔记 > 编程语言 > 正文

如何在SQL中实现过滤系统?

如何解决《如何在SQL中实现过滤系统?》经验,为你挑选了1个好方法。

现在我打算在我的网站上添加一个过滤系统.

例子:

(ID=apple, COLOR=red, TASTE=sweet, ORIGIN=US)
(ID=mango, COLOR=yellow, TASTE=sweet, ORIGIN=MEXICO)
(ID=banana, COLOR=yellow, TASTE=bitter-sweet, ORIGIN=US)

所以现在我有兴趣做以下事情:SELECT ID FROM thisTable WHERE COLOR ='yellow'AND TASTE ='SWEET'

但我的问题是我在我的网站中为多个类别执行此操作,并且列不一致.(如果桌子是用于手机,那么它将是品牌,3G-ENABLED,价格,颜色,波长等)

我怎么能设计一个允许这个的通用模式?

现在我正计划做:

table(ID, KEY, VALUE)

这允许任意数量的列,但对于查询,我使用SELECT ID FROM表WHERE(KEY = X1 AND VALUE = V1)AND(KEY = X2 AND VALUE = V2),..返回空集.

有人可以推荐一个很好的解决方案吗?请注意,列数将定期更改



1> Daniel Vassa..:

您建议的实体属性值模型可适用于此方案.

关于过滤查询,你必须明白,使用EAV模型你会牺牲大量的查询能力,所以这会变得非常棘手.然而,这是解决问题的一种方法:

SELECT    stuff.id 
FROM      stuff 
JOIN      (SELECT    COUNT(*) matches
           FROM      table
           WHERE     (`key` = X1 AND `value` = V1) OR 
                     (`key` = X2 AND `value` = V2) 
           GROUP BY  id
          ) sub_t ON (sub_t.matches = 2 AND sub_t.id = stuff.id)
GROUP BY  stuff.id;

此方法的一个不优雅的特性是您需要指定您希望匹配的属性/值对的数量sub_t.matches = 2.如果我们有三个条件,我们必须指定sub_t.matches = 3,依此类推.

让我们构建一个测试用例:

CREATE TABLE stuff (`id` varchar(20), `key` varchar(20), `value` varchar(20));

INSERT INTO stuff VALUES ('apple',  'color',  'red');
INSERT INTO stuff VALUES ('mango',  'color',  'yellow');
INSERT INTO stuff VALUES ('banana', 'color',  'yellow');

INSERT INTO stuff VALUES ('apple',  'taste',  'sweet');
INSERT INTO stuff VALUES ('mango',  'taste',  'sweet');
INSERT INTO stuff VALUES ('banana', 'taste',  'bitter-sweet');

INSERT INTO stuff VALUES ('apple',  'origin',  'US');
INSERT INTO stuff VALUES ('mango',  'origin',  'MEXICO');
INSERT INTO stuff VALUES ('banana', 'origin',  'US');

查询:

SELECT    stuff.id 
FROM      stuff 
JOIN      (SELECT    COUNT(*) matches, id
           FROM      stuff
           WHERE     (`key` = 'color' AND `value` = 'yellow') OR 
                     (`key` = 'taste' AND `value` = 'sweet')
           GROUP BY  id
          ) sub_t ON (sub_t.matches = 2 AND sub_t.id = stuff.id)
GROUP BY  stuff.id;

结果:

+-------+
| id    |
+-------+
| mango |
+-------+
1 row in set (0.02 sec)

现在让我们用color=yellow和插入另一个水果taste=sweet:

INSERT INTO stuff VALUES ('pear', 'color', 'yellow');
INSERT INTO stuff VALUES ('pear', 'taste', 'sweet');
INSERT INTO stuff VALUES ('pear', 'origin', 'somewhere');

相同的查询将返回:

+-------+
| id    |
+-------+
| mango |
| pear  |
+-------+
2 rows in set (0.00 sec)

如果我们想要将此结果限制为实体origin=MEXICO,我们将不得不添加另一个OR条件并检查sub_t.matches = 3而不是2.

SELECT    stuff.id 
FROM      stuff 
JOIN      (SELECT    COUNT(*) matches, id
           FROM      stuff
           WHERE     (`key` = 'color' AND `value` = 'yellow') OR 
                     (`key` = 'taste' AND `value` = 'sweet') OR 
                     (`key` = 'origin' AND `value` = 'MEXICO')
           GROUP BY  id
          ) sub_t ON (sub_t.matches = 3 AND sub_t.id = stuff.id)
GROUP BY  stuff.id;

结果:

+-------+
| id    |
+-------+
| mango |
+-------+
1 row in set (0.00 sec)

与每种方法一样,使用EAV模型时存在某些优点和缺点.确保在应用程序的上下文中广泛研究该主题.您甚至可能想要考虑其他关系数据库,例如Cassandra,CouchDB,MongoDB,Voldemort,HBase,SimpleDB或其他键值存储.

推荐阅读
和谐啄木鸟
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有