[英]SQL query involving comparison of sets
Products can be sold as bundles. 产品可以捆绑销售。 Following tables are present:
products
, bundles
, bundles_products
, orders
, orders_products
. 下表存在:
products
, bundles
, bundles_products
, orders
, orders_products
。
An order would be said to "contain" a bundle if it contains all the bundle's products. 如果订单包含捆绑软件的所有产品,则该订单将被称为“包含”捆绑软件。
How would one go about counting orders for bundles? 如何计算包的订单数?
products table 产品表
id name
1 broom
2 mug
3 spoon
4 candle
bundles table 捆绑表
id name
1 dining
2 witchcraft
bundles_products table bundles_products表
bundle_id product_id
1 2
1 3
2 1
2 4
orders_products table orders_products表
order_id product_id
1000 1
1000 3
1001 1
1001 2
1001 3
The query would return the following table: 该查询将返回下表:
bundle orders
dining 1
witchcraft 0
The example intentionally misses the orders
table as it is not relevant what it contains. 该示例故意遗漏了
orders
表,因为它与表中所含内容无关。
Of course, this could be approached imperatively, by writing some code and gathering the data, but I was hoping there is a declarative, SQL way of querying for this kind of things? 当然,可以通过编写一些代码并收集数据来强制执行此操作,但我希望有一种声明性的SQL查询此类内容的方法?
One idea I had was to use a GROUP_CONCAT
to concatenate all the products of a bundle and somehow compare that with products of each order. 我曾经有一个想法是使用
GROUP_CONCAT
连接一个捆绑包的所有产品,并以某种方式将其与每个订单的产品进行比较。 Still, a long way from clear. 不过,距离还很遥远。
One way is to use two Derived Tables (subqueries). 一种方法是使用两个派生表 (子查询)。 In first subquery, we will fetch the total number of unique products for every bundle.
在第一个子查询中,我们将获取每个捆绑商品的唯一商品总数。 In the second subquery, we will fetch the total products in an order, for a combination of order and bundle.
在第二个子查询中,我们将按订单和组合商品的组合获取订单中的全部产品。
We will LEFT JOIN
them on bundle_id
as well as matching the total count of products per bundle in them. 我们将在
bundle_id
其LEFT JOIN
,并匹配其中每个捆绑产品的总数。 Eventually, we will do a grouping on bundle, and count the number of orders matching successfully. 最终,我们将对捆绑商品进行分组,并计算成功匹配的订单数量。
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
Here's the brief example, which lacks some parts, I omitted because I don't know precise database structure. 这是一个简短的示例,由于缺少某些部分,因此我省略了,因为我不知道精确的数据库结构。 Logic is such:
逻辑是这样的:
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
Edit: I posted this as a response to previous version of the question, without detailed explanation. 编辑:我张贴这是对问题的先前版本的答复,没有详细说明。
Edit2: fixed query a bit. Edit2:固定查询一点。 It can be starting point.
它可以作为起点。 Logic is still the same, you can get amount of orders for each bundle_id using it
逻辑仍然相同,您可以使用它获取每个bundle_id的订单数量
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.