Reputation: 1877
I have tables like
products product_attributes
================== ========================================
| id | name | | id | product_id | attribute | value |
================== ========================================
| 1 | product 1 | | 1 | 1 | min | 2 |
| 2 | product 2 | | 2 | 1 | max | 5 |
| 3 | product 3 | | 3 | 2 | min | 10 |
| 3 | product 3 | | 4 | 2 | max | 15 |
| .. | ... | | 5 | 3 | min | 1 |
================== | 6 | 3 | max | 100 |
| .. | ... | ... | ... |
========================================
I want to get all the products that fall within a range I can successfully get a list of the ids that fall with-in the range using
SELECT p.id
FROM `products` p INNER JOIN `product_attributes` AS pa ON p.id = pa.product_id
WHERE pa.`min` <= 5 AND pa.`max` >= 5 GROUP BY p.id
This gives me a list of the ids that i need. What i can not get to work is to get a TOTAL count of the ids instead of a list so i can not use the group by and then when i do that it messes up the count.
Is the only way to do this is by using the select above in a subselect and counting the results?
Thanks
Upvotes: 0
Views: 103
Reputation: 49049
Given the structure above, where min and max are on different rows, I would use this:
select count(id) from (
select p.id
from
`products` p INNER JOIN `product_attributes` AS pa
ON p.id = pa.product_id
where (pa.attribute='min' and pa.value>=5) OR
(pa.attribute='max' and pa.value<=5)
group by p.id
having count(*)=2
) s
Upvotes: 1
Reputation: 33945
One approach is to apply the veneer of normalisation to the eav model before attempting to extract any information from it. In this case that might look like this:
SELECT product_id
, MAX(CASE WHEN attribute = 'min' THEN value END) `min`
, MAX(CASE WHEN attribute = 'max' THEN value END) `max`
FROM product_attributes
GROUP
BY product_id;
+------------+------+------+
| product_id | min | max |
+------------+------+------+
| 1 | 2 | 5 |
| 2 | 10 | 15 |
| 3 | 1 | 100 |
| ... | ... | ... |
+------------+------+------+
Now, what was your question again?
Upvotes: 0
Reputation: 80639
Just replace p.id
with COUNT(1)
in the query.
SELECT COUNT(1)
FROM `products` p
INNER JOIN `product_attributes` AS pa
ON p.id = pa.product_id
WHERE pa.`min` <= 5
AND pa.`max` >= 5
GROUP BY p.id
Upvotes: 1