繁体   English   中英

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

[英]How do I write a SQL query to check if a many-to-many relationship on one table is a subset of a many-to-many relationship on another table?

我有一些模型如下:

Product:
  id
  name
  price

Order:
  id
  user
  created

OrderProduct:
  order_id
  product_id

Promo:
  id
  discount

PromoProduct:
  promo_id
  product_id

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

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
                )
        )

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

这应该符合您的标准,即促销中的所有产品需要成为订单的一部分 - 因为q1.ct = q2.ct q1.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

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

创建一个查询以查找每个促销中有多少产品:

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

这可能需要一些调整,但你明白了。

您可以将给定促销产品加入给定订单的产品,如果任何订单产品行返回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

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

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中的关键字。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM