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.