问题描述
我正在研究一个名为 classicmodels 的数据库。您可以在以下位置找到它:https://www.mysqltutorial.org/mysql-sample-database.aspx/
这家公司销售微型模型,这些模型分布在 7 个产品线中:老爷车、老爷车、飞机、卡车和公共汽车、飞机、火车和摩托车。
我想找出 2003 年和 2004 年最畅销的产品线(销量和收入)。
此外,我需要排除已取消的订单。这是由“订单”表中的“状态”列通知的。
因此,显然,我们必须加入三个表:“products”(按每个产品线对结果进行分组)、“orderdetails”(获取销售数量和单位价格)和“orders”(过滤结果) : 仅选择 2003 和 2004 并排除取消的订单)。
此外,有必要声明我们将不得不处理 1:M(一对多)对来解决这个问题,以避免组合/笛卡尔爆炸。
-
products --> orderdetails 是 1:M 关系
-
orderdetails --> 订单是 1:M 的关系
考虑到这一点,我决定创建子查询来建立 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;
结果如下:
现在,我不知道如何将上面子查询生成的表与 'orders' 表连接起来。这是因为它们没有任何可以在 JOIN 中使用的公共列。
如何确定 2003 年和 2004 年最畅销的产品线(以销量和收入计),不包括取消的订单?
您可以在下面检查数据库的关系模式:
解决方法
只需在 JOIN
表和 orders
条件中添加另一个 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
表中,而是希望在聚合结果之前加入.
这只是在 JOIN
列表的末尾添加另一个连接,然后使用 WHERE
子句进行过滤,然后按原样聚合...
SELECT
p.productLine,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;