我有一张名为products
的表格。 ( id,name,price ),一个名为properties
( id,name,type )的表和一个名为product_properties
的表( id,property_id,product_id,value )。
现在,我可以按如下方式过滤产品:
SELECT 'product_properties'.'product_id' FROM 'product_properties' WHERE 'product_properties'.'product_id' IN [list,of,product,ids] AND 'product_properties'.'property_id' = property_id AND 'product_properties'.'value' = 'some value here'
SELECT * FROM 'products' WHERE 'products'.'id' IN [list,of,product,ids]
此方法需要N个过滤器的N + 1个数据库查询。我希望可以在一个查询中将它结合起来。
我尝试了以下操作,但不起作用:
如何通过单个数据库查询(或尽可能少)来实现这一目标?
我正在使用Ruby on Rails,这意味着我希望结果可以在MySQL和SQLite中运行。
谢谢!
答案 0 :(得分:3)
这就是我试图解决的问题:
WITH FILTERS (property_id, filter_value) AS
(
SELECT 1, 'foo'
UNION ALL SELECT 2, 'bar'
UNION ALL SELECT 3, 'baz'
)
SELECT prods.id
FROM products prods
JOIN product_properties props
ON ( props.product_id = prods.id )
JOIN filters f
ON ( f.property_id = props.property_id AND f.filter_value = props.value )
GROUP BY prods.id
HAVING COUNT(1) = ( SELECT COUNT(1) FROM filters )
以下是这样做:
SELECT
到JOIN
正在做的事情。GROUP BY
,并对结果行执行COUNT()
。在HAVING
子句中,检查产品计数是否与过滤器总数相同。如果是,那么它必须匹配所有这些。注意:您可以替代使用UNION
方法,然后对结果执行GROUP BY
和HAVING COUNT()
,看看它是否有效。确保您对ID执行UNION ALL
而不仅仅是UNION
。