[英]SQL query involving comparison of sets
产品可以捆绑销售。 下表存在: products
, bundles
, bundles_products
, orders
, orders_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_id
其LEFT 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
这是一个简短的示例,由于缺少某些部分,因此我省略了,因为我不知道精确的数据库结构。 逻辑是这样的:
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.