0

我有一个名为 Properties(pid, uid, pname, pvalue) 的表。pid 列是自动生成的。每个 uid(用户 id)可以有多个名称值对存储在 pname 和 pvalue 中。

作为输入,我有多个 pname 和 pvalue 的名称值对,它们形成了一个复杂的布尔表达式。

例如:让我们从一个名称值对开始。假设我想检索所有 'favorite_color' 为 'red' 的 uid。

我写了一个 SQL 查询:

SELECT * 
  FROM properties 
 WHERE ((pname = 'favorite_color') and (pvalue = 'red'))

如果我必须检索类似的东西,查询很快就会变得复杂,获取所有 uid,其 'favorite_color' 是 'red' 或 'blue' 并且 'favorite_drink' 是 'juice' 或' 'milk' 并且 'favorite_hobby' 是 'music'或“艺术”等

我写了一个 SQL 查询:

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')))

我得到了正确的表达式,但不幸的是它失败了,因为评估是在每一行上完成的。如果我想在 where 子句中添加更多名称值对怎么办?

问题:

  1. 是否可以为此编写 SQL 查询?

  2. 我的另一个想法是获取每个用户的所有 pname、pvalue 对,使用表达式语言和我的输入名称值 paris 构建动态表达式来评估它。我想到了 apache 的 JEXL。

4

2 回答 2

2

要执行 AND,您需要根据 and-ed 条件执行尽可能多的自联接:

SELECT *
FROM Properties p1, Properties p2, Properties p3
WHERE p1.uid = p2.uid AND p1.uid = p3.uid
AND (p1.pname = 'favorite_color' AND p1.pvalue IN ('red', 'blue'))
AND (p2.pname = 'favorite_drink' AND p2.pvalue IN ('juice', 'milk'))
AND (p3.pname = 'favorite_hobby' AND p2.pvalue IN ('music', 'art'))

编辑:

另一种可能性是对数据进行非规范化,然后使用FIND_IN_SET()or RLIKE

SELECT uid, group_concat(concat(pname, '=', pvalue)) props
FROM Properties
GROUP BY uid
HAVING props RLIKE 'favorite_color=(red|blue)'
AND props RLIKE 'favorite_drink=(juice|milk)'
AND props RLIKE 'favorite_hobby=(music|art)'
于 2012-08-26T03:22:58.543 回答
0
SELECT p1.*,p2.pname,p2.pvalue,p3.pname,p3.pvalue
FROM (
       (Select * 
        from Properties  
        where (pname = 'favorite_color' AND pvalue IN ('red', 'blue')) p1, 
       (Select * 
        from Properties  
        where (pname = 'favorite_drink' AND pvalue IN ('juice','milk')) p2, 
       (Select * 
        from Properties  
        where (pname = 'favorite_hobby' AND pvalue IN ('music', 'art')) p3, 
     )
WHERE p1.uid = p2.uid AND p1.uid = p3.uid
于 2012-08-26T04:30:17.070 回答