2014-04-03 93 views
0

我需要在Rails中構建一個查詢,該查詢返回具有一組特定屬性的人員。我簡化了我的例子。因此,這裏有兩個表:查詢具有多個AND和OR條件的連接表

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一個人一個參考。

在我的查詢我想(例如)提出下列問題:

  1. 給我所有的男性人誰是25歲以上!

    name = 'gender' AND value = 'male'name = 'age' AND value > '25'應該返回1個,記錄(person_id=1)

  2. 給我所有的男性人或人誰是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 

任何想法,並幫助將不勝感激。謝謝!

回答

1

考慮像

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' 

聯合:

1)

SELECT ... 
WHERE attr_gender.value = 'male' 
AND attr_age.value::int > 25 

2)

SELECT ... 
WHERE attr_gender.value = 'male' 
OR attr_age.value::int > 25 

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

+0

我真的很喜歡你的解決方案!剛剛嘗試過。奇蹟般有效。我會將你的帖子標記爲答案。只是想等待其他解決方案,如果有的話。非常感謝你!你保存了一天。 注意:我確實使用CAST(值整數)> 25'進行投射。那是一樣的嗎? – Hiasinho

+0

這是一樣的,此外'CAST()'符合ansi sql。 – pozs

0

你有沒有試過這樣:

(attributes.name = '性別' AND attributes.value = '男')或
(attributes.name = '年齡' AND attributes.value> '25 ')

沒有「GROUP BY」/「HAVING」零件?

+0

是的,試過了。 OR案件不是問題。如果我用'AND'替代'OR',它不起作用。我會用更復雜的例子更新我的文章。 – Hiasinho