我正在尝试创建订单摘要报告,但无法在单个查询中提取所有所需数据。
我要提取的数据:
订单表(本例已简化)
| orderId | deliveryTotal | total |
|---------|---------------|-------|
| 1 | 5 | 15 |
| 2 | 5 | 15 |
| 3 | 7.50 | 27.50 |
订购商品表
| orderItemId | orderId | productId | salePrice | quantity |
|-------------|---------|-----------|-----------|----------|
| 1 | 1 | 1 | 10 | 1 |
| 2 | 2 | 1 | 10 | 1 |
| 3 | 3 | 1 | 10 | 1 |
| 4 | 3 | 2 | 10 | 1 |
我当前提取此数据的查询是
SELECT
SUM(i.salePrice * i.quantity) as subtotal,
SUM(DISTINCT o.deliveryTotal) as deliveryTotal,
COUNT(DISTINCT o.orderId) as orders,
SUM(i.quantity) as quantity
FROM orderItems i
INNER JOIN orders o ON o.orderId = i.orderId
这会产生正确的小计、订单计数和数量总和。但是当我在 17.50 之后,交货总额返回为 12.50。如果我这样做
SUM(o.deliveryTotal)
它将返回 25.
编辑:期望的结果
| subtotal | deliveryTotal | orders | quantity |
|----------|---------------|--------|----------|
| 40.00 | 17.50 | 3 | 4 |
https://tiaashish.wordpress.com/2014/01/31/mysql-sum-for-distinct-rows-with-left-join/
这是一篇博客文章,准确地展示了我正在寻找的内容。也许这也可以帮助其他人。
公式是这样的:
SUM(o.deliveryTotal) * COUNT(DISTINCT o.orderId) / COUNT(*)
由于连接,
SUM(DISTINCT deliveryTotal)
聚合被应用到包含值5, 5, 7.5, 7.5
(不同的5 + 7.5 = 12.5
)的行集。
如果您简单地这样做,
SUM()
所作用的行会变得更加明显
SELECT o.*
FROM orderItems i
INNER JOIN orders o ON o.orderId = i.orderId
相反,您要求的是
SUM()
中所有值的 deliveryTotal
,无论它们在与 orderItems
的连接中的位置如何。这意味着您需要在不同的级别应用聚合。
由于您不打算稍后添加
GROUP BY
,因此最简单的方法是使用子选择,其目的只是在整个表中获取 SUM()
。
SELECT
SUM(i.salePrice * i.quantity) as subtotal,
-- deliveryTotal sum as a subselect
(SELECT SUM(deliveryTotal) FROM orders) as deliveryTotal,
COUNT(DISTINCT o.orderId) as orders,
SUM(i.quantity) as quantity
FROM orderItems i
INNER JOIN orders o ON o.orderId = i.orderId
通常不鼓励使用子选择,但子选择不会造成显着的性能损失,与使用连接的替代方法没有什么不同。无论如何,计算都必须在与现有连接不同的单独聚合上完成。 其他方法会在
CROSS JOIN
子句中放置一个子查询 FROM
,它执行的操作与我们在子查询中放置的操作相同。性能是一样的。
在内部选择中选择每个订单,然后将其汇总
Select
SUM(subtotal) as subtotal,
sum(deliveryTotal) as deliveryTotal,
count(1) as orders,
sum(quantity) as quantity
from (
SELECT
SUM(i.salePrice * i.quantity) as subtotal,
o.deliveryTotal as deliveryTotal,
SUM(i.quantity) as quantity
FROM orders o
INNER JOIN orderItems i ON o.orderId = i.orderId
group by o.orderId) as sub
以下查询结果正是您所需要的
SELECT SUM(conctable.subtotal),
SUM(conctable.deliveryTotal),
SUM(conctable.orders),
SUM(conctable.quantity) from
(SELECT SUM(i.salePrice * i.quantity) as subtotal,
o.deliveryTotal as deliveryTotal,
COUNT(DISTINCT o.orderId) as orders,
SUM(i.quantity) as quantity
FROM orderItems i
JOIN orders o ON o.orderId = i.orderId group by i.orderid) as conctable;
有一种方法可以通过替换来做到这一点:
SUM(columnToAdd)
与
ROUND(SUM(DISTINCT columnToAdd + distinctId/10000), 2)
所以在这种情况下,它将是:
ROUND(SUM(DISTINCT deliveryTotal + orderId/10000), 2)
这会将 DISTINCT(5.0001, 5.0002, 7.5003, 7.5003) = 5.0001 + 5.0002 + 7.5003 = 17.5006 加起来,然后将其舍入为 17.50。由于两个 7.5 来自 id 为 3 的同一订单,因此它们将作为重复项被删除。但这两个 5 来自不同的顺序,因此不是重复的。
这只适用于 ID 号较小的情况(除以 10000 不会干扰 SUM)。如果你有更大的 id 数字,你必须除以一个更大的数字并输入 FORMAT 来强制 MySQL 使用超过 4 位小数:
ROUND(SUM(DISTINCT FORMAT(columnToAdd + distinctId/10000000000, 12)), 2)
我承认这是对旧帖子的一个相当丑陋的答案,但我今天正在寻找解决方案并记得过去做过类似的事情。