一列的MySQL SUM,ID列的DISTINCT

时间:2016-02-04 13:25:05

标签: mysql

我正在尝试创建订单的摘要报告,但无法在单个查询中提取所有必需的数据。

我想提取的数据:

  • 小计 - 所有销售价格的总和
  • 交货总额 - 所有订单交货的总数
  • 订单 - DISTINCT orderIds的COUNT
  • 数量 - 订购的所有数量的总和

订单表(本例简化)

| 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        |

4 个答案:

答案 0 :(得分:4)

由于加入,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,它执行我们在子选择中放置的相同内容。表现会一样。

答案 1 :(得分:1)

在内部选择中选择每个订单而不是总结

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

答案 2 :(得分:0)

以下查询确切地显示了您的需求

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;

答案 3 :(得分:0)

https://tiaashish.wordpress.com/2014/01/31/mysql-sum-for-distinct-rows-with-left-join/

这是一篇博客文章,准确显示了我在寻找什么。也许这也可以帮助其他人。

公式如下:

SUM(o.deliveryTotal) * COUNT(DISTINCT o.orderId) / COUNT(*)