Sumair Rasool :
I have a table person, which is like this,
Persons
id | name
1 | Alex
2 | Jack
3 | Roy
I have an other table
Properties
id | title | format
1 | Age | number
2 | Plays Football | checkbox
3 | Weight | number
Persons and Properties have many to many relation through a third table PersonProperties.
PersonProperties
PersonId | PropertyId | value
1 | 1 | 24
1 | 2 | true
2 | 1 | 43
I want to filter out persons having age 20 to 30 and plays football. As i already have ids of Age and Plays Football with their values which are id 1 (min = 20, max = 30) and id 2 (true). To get that i query like this,
SELECT `Persons`.`id`,`name` FROM `Persons`
INNER JOIN `PersonProperties` ON `Persons`.id = `PersonProperties`.`PersonId`
WHERE ((`PersonProperties`.`value` >= 20 AND `PersonProperties`.`value` <= 30) AND `PersonProperties`.`PropertyId` = 1)
AND (`PersonProperties`.`value` = true AND `PersonProperties`.`PropertyId` = 2)
GROUP BY `Persons`.`id`
It return empty result.
Desired Outcome
id | name
1 | Alex
Gordon Linoff :
Your version doesn't work, because no single row can match both conditions. You need to match across rows.
Use aggregation for this:
SELECT p.id, p.name
FROM Persons p JOIN
PersonProperties pp
ON p.id = pp.PersonId
WHERE (p.PropertyId = 1 AND (p.value + 0) >= 20 AND (p.value + 0) <= 30) OR
(p.PropertyId = 2 AND p.value = 'true')
GROUP BY p.id, p.name
HAVING COUNT(*) = 2; -- both match
Notes:
- Table aliases make a query much easier to write and to read.
- Backticks make a query harder to write and to read.
Value
is a string (presumably). Hence, you need to be careful with comparisons. I added the(+ 0)
to be clear that a conversion is involved.
Guess you like
Origin http://43.154.161.224:23101/article/api/json?id=372367&siteId=1