表上的多维搜索
我有下表存储系统中用户的首选项,
UserId | Product | Brand | City |
-------------------------------------------
A | Soap | Tide | NYC |
A | Cereal | Dont-care | NYC |
B | Dont-Care | Tide | Dont-care |
C | Shampoo | Dont-care | Dont-Care |
我想根据用户提供的搜索值进行搜索。因此,如果一个人搜索
City: NYC, Brand: Tide
输出应该是:
A | Soap | Tide | NYC |
B | Dont-Care | Tide | Dont-care |
就好像他们搜索
Brand: Tide, Product: Soap
结果应该是:
A | Soap | Tide | NYC |
当前的解决方案是针对 MySQL 表的以下查询(其中 null 代表“不关心”):
select *
from user_preferences
where (product is null or product = <user provided value>)
and (brand is null or brand = <user provided value>)
and (city is null or city = <user provided value>)
我 按预期工作,[和+(或)]组合让我认为这不是正确的方法。我也相当确定,一旦数据集增加,查询将无法很好地执行。
存储和检索此类数据的最有效方法是什么?是否有任何 no-sql 类型的方法可以用来提高效率?
更新
经过一番谷歌搜索后,我认为我的方法可能是最安全的选择。我对这种方法仍然感到矛盾的一个因素是添加另一个“可搜索”属性意味着添加一个新列。
这篇关于 EAV 反模式的博客提供了一些关于此类的很好的阅读材料一个计划。另请参阅 friend-feed 如何使用 MySQL 来了解存储变量属性的另一种方式在一个表中。
I have the following table that stores the preferences of the users in the system
UserId | Product | Brand | City |
-------------------------------------------
A | Soap | Tide | NYC |
A | Cereal | Dont-care | NYC |
B | Dont-Care | Tide | Dont-care |
C | Shampoo | Dont-care | Dont-Care |
I would like to search this based on user provided search values. So if one searches for
City: NYC, Brand: Tide
the output should be:
A | Soap | Tide | NYC |
B | Dont-Care | Tide | Dont-care |
where as if they search for
Brand: Tide, Product: Soap
the result should be:
A | Soap | Tide | NYC |
The current solution I have, is the following query (where null represents 'don't care') going against a MySQL table:
select *
from user_preferences
where (product is null or product = <user provided value>)
and (brand is null or brand = <user provided value>)
and (city is null or city = <user provided value>)
Though it works as expected, the [and + (or)] combination makes me think this is not the right way to do this. I am also fairly certain that once the dataset increases, the query will not perform well.
What would be most efficient way of storing and retrieving such data? Are there any no-sql type approaches that can be used to make this efficient?
Update
After some googling around I figured the approach I have may be the safest bet. One factor I still am ambivalent about with this approach is that adding another 'searchable' attribute would mean adding a new column.
This blog about the EAV anti-pattern provides some good reading material on such a scheme. Also see how friend-feed uses MySQL for another take on storing variable attributes in a table.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您可以使用 IFNULL() 函数。
它会是这样的:
You could use the IFNULL() function.
It would be something like this:
我是一个 oracle pl sql 开发人员,所以请检查上面的查询是否有 oracle sql 的语法。
如果在您的数据库中
ifnull
是检查 null 值的函数,请将nvl()
替换为ifnull
()@Pompom6784 您必须应用 ifnull上<用户提供的价值>不在列值上..
I am a oracle pl sql developer so please check above query having syntex of oracle sql..
if in your database
ifnull
is the function to check for null values please replacenvl()
withifnull
()@Pompom6784 you had to apply ifnull on < user provided value > not on column values ..
既然您问如何存储此类数据,那么我可能会这样做:
上面的 PREFTYPEVALUES 表允许您限制 USERPREFS 表中可能的值条目:
要合并两组用户,第一组是那些喜欢 Tide 的用户他们的肥皂和第二组是那些更喜欢纽约市作为其城市的人,您可以将这两个组联合起来:
但当然,这种结构也允许不使用联合的查询。
我打赌您的下一个问题将是:如何为每个用户获取一行,并并排显示用户的首选项?
这种非规范化最好留给表示层,尽管可以使用各种不优雅的方法在 SQL 中完成。这里的 SQL 键是复合的 (user,preftype)。
Since you ask how to store such data, here's what I'd probably do:
PREFTYPEVALUES table above lets you constrain the possible value-entries in the USERPREFS table:
To combine the two sets of users, the first set being those who prefer Tide for their soap and the second set being those who prefer NYC as their city, you could UNION the two sets:
but this structure would also permit queries that do not use UNION, of course.
I bet your next question would be: how to get a single row for each user, with the user's preferences side-by-side?
That denormalization is better left to the presentation layer, although it can be done in SQL using a variety of inelegant approaches. The SQL key here is composite (user,preftype).