如何在不生成 'combinatorial explosion' - MySQL 的情况下连接表

How to Join tables without generating a 'combinatorial explosion' - MySQL

我正在处理一个名为 classicmodels 的数据库。您可以在以下位置找到它:https://www.mysqltutorial.org/mysql-sample-database.aspx/

该公司销售微缩模型,产品分布在 7 个产品系列中:老爷车、老爷车、飞机、卡车和公共汽车、飞机、火车和摩托车。

我想了解哪些是 2003 年和 2004 年最畅销的产品线(以销售量和收入计)。

此外,我需要排除已取消的订单。这是由 'orders' table 中的 'status' 列告知的。

所以,显然,我们必须连接三个 tables:'products'(按每个产品线对结果进行分组),'orderdetails'(以获得销售数量和每个产品的价格单位)和 'orders'(过滤结果:select 仅 2003 年和 2004 年并排除已取消的订单)。

此外,需要说明的是,我们必须处理 1:M(一对多)对来解决这个问题,以避免 combinatorial/cartesian 爆炸。

考虑到这一点,我决定创建子查询来建立 1:1 关系。因此,我计算了订购数量和每个产品线的总价值:

SELECT p.productLine, SUM(od.quantityOrdered) AS total_units, SUM(od.quantityOrdered*od.PriceEach) AS total_value
FROM products p
    JOIN
orderdetails od ON p.productCode=od.productCode
GROUP BY p.productLine
ORDER BY total_value DESC;

结果如下:

现在,我不知道如何将上述子查询生成的table 与'orders' table 连接起来。这是因为它们没有任何可以在 JOIN 中使用的公共列。

如何确定 2003 年和 2004 年最畅销的产品线(以销售量和收入计),不包括取消的订单?

您可以在下面检查数据库的关系模式:

只需添加另一个 JOINorders table 和 WHERE 条件以限制您想要的订单。

SELECT p.productLine, SUM(od.quantityOrdered) AS total_units, SUM(od.quantityOrdered*od.PriceEach) AS total_value
FROM products p
JOIN orderdetails od ON p.productCode=od.productCode
JOIN orders o ON o.orderNumber = od.orderNumber
WHERE o.orderDate BETWEEN '2003-01-01' AND '2004-12-31'
    AND o.status != 'cancelled'
GROUP BY p.productLine
ORDER BY total_value DESC;

您不想将您在 orders table 上的结果加入 before[=] 20=] 您汇总了结果。

这只是将另一个连接添加到 JOIN 列表的末尾,然后使用 WHERE 子句进行过滤,然后像您已经做的那样聚合...

SELECT
  p.productLine,
  SUM(od.quantityOrdered) AS total_units,
  SUM(od.quantityOrdered*od.PriceEach) AS total_value
FROM
  products       p
INNER JOIN
  orderdetails   od
    ON p.productCode = od.productCode
INNER JOIN
  orders         o
    ON o.orderNumber = od.orderNumber
WHERE
      o.status    != 'Cancelled'
  AND o.orderDate >= '2003-01-01'
  AND o.orderDate <  '2005-01-01'  -- Less than the next year, in case the date includes a time
GROUP BY
  p.productLine
ORDER BY
  total_value DESC;