繁体   English   中英

涉及集合比较的SQL查询

[英]SQL query involving comparison of sets

背景

产品可以捆绑销售。 下表存在: productsbundlesbundles_productsordersorders_products

如果订单包含捆绑软件的所有产品,则该订单将被称为“包含”捆绑软件。

问题

如何计算包的订单数?

产品

id  name
1   broom
2   mug
3   spoon
4   candle

捆绑

id  name
1   dining
2   witchcraft

bundles_products

bundle_id product_id
1         2
1         3
2         1
2         4

orders_products

order_id  product_id
1000      1
1000      3
1001      1
1001      2
1001      3

该查询将返回下表:

bundle     orders
dining     1
witchcraft 0

笔记

该示例故意遗漏了orders表,因为它与表中所含内容无关。

当然,可以通过编写一些代码并收集数据来强制执行此操作,但我希望有一种声明性的SQL查询此类内容的方法?

我曾经有一个想法是使用GROUP_CONCAT连接一个捆绑包的所有产品,并以某种方式将其与每个订单的产品进行比较。 不过,距离还很遥远。

一种方法是使用两个派生表 (子查询)。 在第一个子查询中,我们将获取每个捆绑商品的唯一商品总数。 在第二个子查询中,我们将按订单和组合商品的组合获取订单中的全部产品。

我们将在bundle_idLEFT JOIN ,并匹配其中每个捆绑产品的总数。 最终,我们将对捆绑商品进行分组,并计算成功匹配的订单数量。

SELECT dt1.id              AS bundle_id,
       dt1.name            AS bundle,
       Count(dt2.order_id) AS orders
FROM   (SELECT b.id,
               b.name,
               Count(DISTINCT bp.product_id) AS total_bundle_products
        FROM   bundles AS b
               JOIN bundles_products AS bp
                 ON bp.bundle_id = b.id
        GROUP  BY b.id,
                  b.name) AS dt1
       LEFT JOIN (SELECT op.order_id,
                         bp.bundle_id,
                         Count(DISTINCT op.product_id) AS order_bundle_products
                  FROM   orders_products AS op
                         JOIN bundles_products AS bp
                           ON bp.product_id = op.product_id
                  GROUP  BY bp.bundle_id,
                            op.order_id) AS dt2
              ON dt2.bundle_id = dt1.id
                 AND dt2.order_bundle_products = dt1.total_bundle_products
GROUP  BY dt1.id,
          dt1.name 

SQL小提琴演示

这是一个简短的示例,由于缺少某些部分,因此我省略了,因为我不知道精确的数据库结构。 逻辑是这样的:

  1. 生成临时表,该表由3行组成-订单,与捆绑商品相关的产品数量,捆绑商品数量
  2. 然后,我们仅从该表中选择订单,在该订单中我们最后两个变量相等
select count(order_id) from orders 
    left join(
        select count(*) from bundles_products as bundle_amount, 
                  sum(case when orders_products in (
                  select names from bundles_products where bundle_id='1') then 1 else 0) as order_total, 
                  orders.order_id 
            left join product on bundle_products.product_id = products.product_id
            left join orders on products.product_id = orders_products.product_id
        where bundle_products.bundle_id ='1'
        ) as my_table 
        on orders.order_name = my_table.orders 
        where my_table.bundle_amount = my_table.order_total

编辑:我张贴这是对问题的先前版本的答复,没有详细说明。

Edit2:固定查询一点。 它可以作为起点。 逻辑仍然相同,您可以使用它获取每个bundle_id的订单数量

暂无
暂无

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

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