如何编写SQL查询以检查一个表上的多对多关系是否是另一个表上多对多关系的子集?

时间:2011-07-26 21:10:51

标签: mysql sql

我有一些模型如下:

Product:
  id
  name
  price

Order:
  id
  user
  created

OrderProduct:
  order_id
  product_id

Promo:
  id
  discount

PromoProduct:
  promo_id
  product_id

如果促销中的所有产品都在订单中,则促销适用于订单。如何编写SQL查询以查找适用于订单的促销活动?

5 个答案:

答案 0 :(得分:4)

SELECT  *
FROM    promo p
WHERE   id NOT IN
        (
        SELECT  pp.promo_id
        FROM    promoProduct pp
        WHERE   pp.product_id NOT IN
                (
                SELECT  product_id
                FROM    orderProduct op
                WHERE   op.order_id = $order
                )
        )

请注意,这也会返回所有带有空产品列表的促销活动(“这个机库中没有我无法飞行的飞机”)。如果这是一个问题,您将需要额外检查促销的非空虚。

答案 1 :(得分:1)

这应该符合您的标准,所有促销中的产品需要成为订单的一部分 - 因为q1.ct = q2.ctq1.ct为您提供每个促销订单的产品数量; q2.ct为您提供每个订单的产品总数。

显然,您可以进一步将其加入订单和促销表中,以便在结果集中获得您想要的任何其他信息。

SELECT q1.order_id, q1.promo_id FROM
( SELECT op.order_id, pp.promo_id, COUNT( op.product_id ) AS ct
FROM OrderProduct op INNER JOIN PromoProduct pp ON product_id
GROUP BY op.order_id, pp.promo_id ) q1

INNER JOIN

( SELECT pp.promo_id, COUNT( pp.product_id ) AS ct
FROM PromoProduct pp
GROUP BY pp.promo_id ) q2

ON q1.promo_id = q2.promo_id AND q1.ct = q2.ct

答案 2 :(得分:1)

使用子查询可以分而治之。

创建查询以查找每个促销中的产品数量:

SELECT promo_id, COUNT(product_id) AS no_products
FROM PromoProduct
GROUP BY promo_id

然后创建另一个以查找促销中每个订单的产品数量:

SELECT OP.order_id, PP.promo_id, COUNT(OP.product_id) AS no_products
FROM OrderProduct OP
INNER JOIN PromoProduct PP ON OP.product_id = PP.product_id
GROUP BY OP.order_id, PP.promo_id

然后将他们加在一起:

SELECT OP.order_id, PP.promo_id
FROM OrderProduct OP
INNER JOIN PromoProduct PP ON OP.product_id = PP.product_id
INNER JOIN (SELECT promo_id, COUNT(product_id) AS no_products
FROM PromoProduct
GROUP BY promo_id) PC ON PP.promo_id = PC.promo_id AND COUNT(OP.product_id) = PC.no_products
GROUP BY OP.order_id, PP.promo_id

这可能需要稍加调整,但你明白了。

答案 3 :(得分:0)

您可以将给定促销的产品加入给定订单的产品,如果任何订单产品行返回null,则表示该订单不符合该促销的条件,因为您对合格所需的定义促销。

编辑:

        select promoproducts.productid, orderproducts.productid
        from promoproducts
        left join orderproducts
        on promoproducts.productid = orderproducts.productid
        where promoid = 'x' and orderid = 'y'

EDIT2:忽略上面(见Quassnoi的评论);我建议的方法需要作为内联视图的LEFT JOIN来完成:

        select pp.productid as promoproduct, orderproduct
        from promoproducts pp
        left join 

          (
         select productid as orderproduct
           from orderproducts
           where orderid=1

         ) as op
         on pp.productid=op.orderproduct
          where promoid =1

EDIT3:不是将订单与特定促销(where promoid = x)进行比较,而是将其与所有当前促销进行比较:

          ...  where promoid in (select promoid from promos where startdate ... expirydate ...) 
           -- find current promos

这种左连接方法的真实优势在于它向您展示了订单符合条件的所有促销,以及它不符合以及哪些产品具有的所有促销要添加到订单中以获得促销资格

答案 4 :(得分:-1)

SELECT *
FROM 'order' o
INNER JOIN orderproduct op ON op.order_id = o.order_id
INNER JOIN PromoProduct p ON p.product_id = op.product_id
WHERE o.order_id = ?

试试..虽然我认为你应该重命名订单表,因为它是MySQL中的关键字。