Ruby on rails 查询具有多个AND或条件的联接表

Ruby on rails 查询具有多个AND或条件的联接表,ruby-on-rails,postgresql,activerecord,ruby-on-rails-4,arel,Ruby On Rails,Postgresql,Activerecord,Ruby On Rails 4,Arel,我需要在Rails中构建一个查询,返回具有特定属性集的人。我简化了我的例子。下面是两张表: Table: people +----+----------+ | id | name | +----+----------+ | 1 | Person A | | 2 | Person B | | 3 | Person C | +----+----------+ Table: attributes +----+-----------+--------+--------+ | id | p

我需要在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\u id
是对表
people
中人员的引用

在我的询问中,我想(例如)问以下问题:

  • 给我找所有25岁以上的男性

    name='gender'和value='male'
    name='age'和value>'25'
    应返回1条记录
    (person\u id=1)

  • 给我找所有男性或25岁以上的人

    name='gender'和value='female'
    name='age'和value>'25'
    应返回2条记录
    (person\u id=1和3)

  • 例2并不难做到。但我对示例1有一些问题。我不知道如何处理这里的
    。不要忘了:
    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
    
    任何想法和帮助都将不胜感激。谢谢

    你试过这个吗:

    (attributes.name='gender'和attributes.value='male')或
    (attributes.name='age'和attributes.value>'25')


    如果没有“groupby”/“HAVING”部件,请考虑以下内容

    SELECT people.* 
    FROM people
    LEFT JOIN attributes AS attr_gender
        ON attr_gender.person_id = people.id 
        AND attr_gender.name = 'gender'
    LEFT JOIN attributes AS attr_age
        ON attr_age.person_id = people.id 
        AND attr_age.name = 'age'
    
    结合:

    (一)

    (二)


    注意:铸造是必要的-
    '9'>'25'

    是的,试过了。OR案例不是问题所在。如果我用
    替换
    ,则它不起作用。我将用一个更复杂的例子更新我的帖子。我真的很喜欢你的解决方案!我试过了。工作起来很有魅力。我会把你的帖子标记为答案。只是想等待其他解决方案,如果有的话。非常感谢你!你挽救了这一天。注意:我使用
    CAST(值为整数)>25进行了强制转换。这是一样的吗?这是一样的,而且
    CAST()
    符合ansi sql。
    SELECT ...
    WHERE attr_gender.value = 'male'
    AND attr_age.value::int > 25
    
    SELECT ...
    WHERE attr_gender.value = 'male'
    OR attr_age.value::int > 25