Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/ant/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql SQL:按属性列表筛选产品_Mysql_Sql_Join_Filtering_Union - Fatal编程技术网

Mysql SQL:按属性列表筛选产品

Mysql SQL:按属性列表筛选产品,mysql,sql,join,filtering,union,Mysql,Sql,Join,Filtering,Union,我有一张名为products的表。(id,name,price),一个名为properties(id,name,type)的表和一个名为product\u properties(id,property\u id,product\u id,value)的表 现在,我可以按如下方式过滤产品: 从产品标识列表开始 对于我们要筛选的每个(属性、值): product_id=选择“product_properties”。“product_id”来自“product_properties”,其中“produ

我有一张名为
products
的表。(id,name,price),一个名为
properties
(id,name,type)的表和一个名为
product\u properties
(id,property\u id,product\u id,value)的表

现在,我可以按如下方式过滤产品:

  • 从产品标识列表开始
  • 对于我们要筛选的每个(属性、值):
  • product_id=
    选择“product_properties”。“product_id”来自“product_properties”,其中“product_properties”。[list,of,product,ids]中的“product_id”和“product_properties”。“property_id”=property_id和“product_properties”。“value”=“此处的某些值”
  • 重复步骤2,直到筛选出所有想要的属性
  • 最后,使用
    select*从'products'中选择所有匹配的产品,其中'products.'id'位于[list,of,product,ids]
  • 此方法需要对N个筛选器进行N+1个数据库查询。我希望有可能在一个问题中结合这一点

    我尝试了以下方法,但无效:

    • 内部联接/外部联接->放弃除第一个以外指向产品行的所有产品属性,然后尝试对其强制所有N ID和值
    • UNION->返回一个列表,其中包含与一个或多个筛选器匹配的产品,而不是所有筛选器
    如何通过单个数据库查询(或尽可能少的查询)实现这一点

    我正在使用RubyonRails,这意味着我希望结果能够在MySQL和SQLite中工作


    谢谢大家!

    这就是我试图解决这个问题的方法:

    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 )
    
    这就是它所做的:

    • 首先,将过滤器列表作为“WITH”子句的一部分提供,以便它可以位于同一查询中。我假设在3个不同的属性上添加3个过滤器,它们的值分别为“foo”、“bar”和“baz”
    • 其次,执行一个将过滤器与产品匹配的查询。这是
      通过
      JOIN
      选择的操作
    • 第三,对产品id执行
      groupby
      ,并对结果行执行
      COUNT()。在
      HAVING
      子句中,检查产品计数是否与过滤器总数相同。如果是的话,那么它一定匹配了所有这些

    注意:您可以交替使用
    UNION
    方法,然后对结果执行
    groupby
    HAVING COUNT()
    ,以查看其是否有效。只需确保在ID上执行
    UNION ALL
    ,而不仅仅是
    UNION

    这就是我试图解决它的方法:

    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 )
    
    这就是它所做的:

    • 首先,将过滤器列表作为“WITH”子句的一部分提供,以便它可以位于同一查询中。我假设在3个不同的属性上添加3个过滤器,它们的值分别为“foo”、“bar”和“baz”
    • 其次,执行一个将过滤器与产品匹配的查询。这是
      通过
      JOIN
      选择的操作
    • 第三,对产品id执行
      groupby
      ,并对结果行执行
      COUNT()。在
      HAVING
      子句中,检查产品计数是否与过滤器总数相同。如果是的话,那么它一定匹配了所有这些

    注意:您可以交替使用
    UNION
    方法,然后对结果执行
    groupby
    HAVING COUNT()
    ,以查看其是否有效。只需确保在ID上执行
    UNION-ALL
    ,而不仅仅是
    UNION

    OP请求的MySQL和SQLite兼容解决方案。而在2014年初,SQLite 3.8.3提供了CTE,MySQL没有,所以
    With()
    将无法工作。哇!
    联合所有。。。分组方式。。。使用COUNT()方法可以完美地工作。一个很好的把戏。非常感谢你!OP请求了一个MySQL和SQLite兼容的解决方案。而在2014年初,SQLite 3.8.3提供了CTE,MySQL没有,所以
    With()
    将无法工作。哇!
    联合所有。。。分组方式。。。使用COUNT()方法可以完美地工作。一个很好的把戏。非常感谢你!