I have a table called Properties (pid, uid, pname, pvalue). The pid column is auto generated. Each uid (user id) could have multiple name value pairs stored in the pname and pvalue.
As an input I’ve multiple name value pairs for pname and pvalue which forms a complicated boolean expression.
For example: let’s start w/ one name value pair. Say I want to retrieve all uid’s whose ‘favorite_color’ is ‘red’.
I wrote an SQL query:
SELECT *
FROM properties
WHERE ((pname = 'favorite_color') and (pvalue = 'red'))
The query soon gets complicated if I had to retrieve something like, fetch all uid’s whose ‘favorite_color’ is ‘red’ or ‘blue’ and ‘favorite_drink’ is ‘juice’ or ‘ ‘milk’ and ‘favorite_ hobby’ is ‘music’ or ‘art’ etc.
I wrote an SQL query:
SELECT *
FROM properties
WHERE (((pname = 'favorite_color') and (pvalue = 'red'))
OR ((pname = 'favorite_color') and (pvalue = 'blue')))
AND (((pname = 'favorite_drink') and (pvalue = 'juice'))
OR ((pname = 'favorite_drink') and (pvalue = 'milk')))
AND (((pname = 'favorite_hobby') and (pvalue = 'music'))
OR ((pname = 'favorite_hobby') and (pvalue = 'art')))
I got the expression correct but unfortunately it fails because the evaluation is done on each row. What if I wanted to add more name value pairs to the where clause?
Questions:
-
Is it possible to write and SQL query for this?
-
The other idea I had was to fetch all the pname, pvalue pairs for each user, build a dynamic expression using an expression language and my input name value paris to evaluate it. I’ve apache’s JEXL in mind.
To do the ANDs you need to do as many self-joins as you have and-ed conditions:
EDIT:
Another possibility is to denormalize the data, and then use
FIND_IN_SET()orRLIKE: