仍然对MySQL中的子查询和子查询感到困惑

时间:2011-06-07 14:56:41

标签: mysql subquery having

我正在尝试根据产品类别页面的构面选择产品。

基本结构是:

Product_Facets
--------------------------------
UID      ProductID       FacetID       FacetOptionID
 1           1              1               1
 2           1              1               2
 3           1              2               4
 4           1              2               7
Products
--------------------------------
ProductID      ProductName
    1           Some Widget

我想选择所有将构面记录设置为用户所选构面的所有的正确值的产品。

所以,如果我有以下要求:
方面ID 1设置为值6和
方面ID 2设置为值97和
方面ID 5设置为值43和

我希望查询从product表中获取所有产品的facet表中具有 ALL 的facet记录的所有产品。查询不应返回仅满足某些要求的产品。

我想我需要在having子句中进行子查询,但我不确定它是如何构建的?

2 个答案:

答案 0 :(得分:3)

一种方法是使用EXISTS子句,您可以根据请求动态生成:

select p.*
from Products p 
where 
   exists (select 1 from Product_Facets where ProductID = p.ProductID
                                        and FacetID = 1
                                        and FacetOptionID= 6)
and
   exists (select 1 from Product_Facets where ProductID = p.ProductID
                                        and FacetID = 2
                                        and FacetOptionID= 97)
and
   exists (select 1 from Product_Facets where ProductID = p.ProductID
                                        and FacetID = 3
                                        and FacetOptionID = 43)

另一种方法是直接内部连接(也很容易动态生成):

select p.*
from Products p
join Product_Facets f1 on p.ProductID = f1.ProductID
         and f1.FacetID = 1 and f1.FacetOptionID = 6
join Product_Facets f2 on p.ProductID = f2.ProductID
         and f2.FacetID = 2 and f2.FacetOptionID = 97
join Product_Facets f3 on p.ProductID = f3.ProductID
         and f3.FacetID = 3 and f3.FacetOptionID = 43

任何一种方法都只返回产品中的记录,其中每个请求的FacetID和FacetOptionID都存在Product_Facets记录(我假设这是您提到的值字段。)

答案 1 :(得分:0)

我会从facets表中预先查询匹配并应用HAVING计数的实体与您选择的标准完全相同,然后将其连接到products表。

第一个“PreQuery”对每个组合应用“OR”作为单独测试每一行......但是HAVING子句确保所有3个条件都符合要求。

SELECT STRAIGHT_JOIN
      P.*
   FROM
      ( select pf.ProductID,
               count(*) as MatchedCriteria
           from
              Product_Facets pf
           where
                 (pf.FacetID = 1 AND FacetOptionID = 6 )
              OR (pf.FacetID = 2 AND FacetOptionID = 97 )
              OR (pf.FacetID = 5 AND FacetOptionID = 43 )
           group by
              pf.ProductID
           having
              count(*) = 3 ) PreQuery

      Join Products p
         on PreQuery.ProductID = p.ProductID
   order by
      p.ProductName