【发布时间】:2014-04-03 13:31:05
【问题描述】:
我需要在 Rails 中构建一个查询,返回具有特定属性集的人。我简化了我的例子。所以这里有两张表:
Table: people
+----+----------+
| id | name |
+----+----------+
| 1 | Person A |
| 2 | Person B |
| 3 | Person C |
+----+----------+
Table: attributes
+----+-----------+--------+--------+
| id | person_id | name | value |
+----+-----------+--------+--------+
| 1 | 1 | age | 32 |
| 2 | 1 | gender | male |
| 3 | 2 | age | 16 |
| 4 | 2 | gender | male |
| 5 | 3 | gender | female |
+----+-----------+--------+--------+
person_id 是对表people 中一个人的引用。
在我的查询中,我想(例如)提出以下问题:
-
把所有 25 岁以上的男性都给我!
name = 'gender' AND value = 'male'和name = 'age' AND value > '25'应该返回 1 条记录(person_id=1) -
把所有男性或 25 岁以上的人都给我!
name = 'gender' AND value = 'female'或name = 'age' AND value > '25'应该返回 2 条记录(person_id=1 and 3)
示例 2 并不难做到。但是我对示例 1 有疑问。我不知道如何处理这里的 AND。不要忘记:WHERE 语句是动态的。意味着可以有很多,也可以只有一个。
基本上,我正在寻找正确的 SQL 语句来执行此操作。我已经玩了一点,到目前为止我得到的最好的东西是:
SELECT people.*
FROM people
INNER JOIN attributes ON attributes.person_id = people.id
WHERE
attributes.name = 'gender' AND attributes.value = 'male' OR
attributes.name = 'age' AND attributes.value > '25'
GROUP BY people.id
HAVING count(*) = 2
我不喜欢这个解决方案,因为我必须在HAVING 子句中指定匹配数。必须有更优雅、更灵活的解决方案才能做到这一点。
下面是一个更复杂但不起作用的例子:
SELECT people.*
FROM people
INNER JOIN attributes ON attributes.person_id = people.id
WHERE
(attributes.name = 'gender' AND attributes.value = 'male') OR
(attributes.name = 'age' AND attributes.value > '25') AND
(attributes.name = 'bodysize' AND attributes.value > '180')
GROUP BY people.id
我们将不胜感激任何想法和帮助。谢谢!
【问题讨论】:
标签: ruby-on-rails postgresql activerecord ruby-on-rails-4 arel