MySQL减去两个相似的行,并将结果乘以另一行

时间:2013-05-29 02:12:40

标签: mysql sum distinct

我希望能够从同一个区域,类型和操作系统中减去ondemand的数量到保留,然后将剩余的数量乘以速率。

以下是mysql数据的示例转储

| Zone  | Type  | Qty | OS    | Reservation | Rate  |
| zone1 | type1 | 12  | linux | ondemand    | 0.24  |
| zone1 | type1 | 6   | linux | reserved    | 0.056 |
| zone1 | type2 | 3   | linux | ondemand    | 0.82  |
| zone2 | type1 | 5   | mswin | ondemand    | 0.24  |
| zone2 | type1 | 2   | mswin | reserved    | 0.056 |
| zone2 | type2 | 3   | linux | ondemand    | 0.82  |
| zone3 | type1 | 4   | linux | ondemand    | 0.24  |
| zone3 | type1 | 1   | linux | reserved    | 0.056 |

结果将是

| Zone  | Type  | Qty | OS    | Reservation | Rate  | sum() |
| zone1 | type1 | 6   | linux | ondemand    | 0.24  | 1.44  |
| zone1 | type1 | 6   | linux | reserved    | 0.056 | 0.336 |
| zone1 | type2 | 3   | linux | ondemand    | 0.82  | 0.246 |
| zone2 | type1 | 3   | mswin | ondemand    | 0.24  | 0.72  |
| zone2 | type1 | 2   | mswin | reserved    | 0.056 | 0.112 |
| zone2 | type2 | 3   | linux | ondemand    | 0.82  | 0.246 |
| zone3 | type1 | 3   | linux | ondemand    | 0.24  | 0.72  |
| zone3 | type1 | 1   | linux | reserved    | 0.056 | 0.056 |

我不确定如何获得一个明确的声明来解决这个问题。我不知道这是否可以使用mysql,或者我是否需要编写脚本然后生成输出。任何帮助表示赞赏。

对于包含ondemand的类型和操作系统,区域中并不总是有相应的保留。

2 个答案:

答案 0 :(得分:1)

您需要将表格加入自身:

select
    t1.Zone, t1.Type, t1.Qty - ifnull(t2.Qty, 0), t1.OS,
    t1.rate, (t1.Qty - ifnull(t2.Qty, 0)) * t1.rate as total
from mytable t1
left join mytable t2
    on t1.zone = t2.zone
    and t1.type = t2.type
    and t1.os = t2.os
    and t2.reservation = 'reserved'

和t1.reservation ='ondemand'

关键功夫是连接条件中的最后一个条件。它确保只有“ondemand”行的连接 - 使用left join,所有其他行类型(以及没有相应“保留”行的那些“ondenand”行)将获得null为join qty值(因此ifnull()给他们一个零来处理)。

请注意,即使“ondemand”行没有匹配的“保留”行,这也会正确计算总数。

说实话,我之前从未见过这种查询,只有某些来自父端的行被加入,但所有行都被保留

答案 1 :(得分:0)

这还没有运行,但这样的事情可能会吗?

select zone, type, os, ondemand_cnt, reserved_cnt, ondemand_cnt-reserved_cnt as cnt, 
<some_rate>*(ondemand_cnt-reserved_cnt) as calc_rate
from
(
select zone, type, os, sum(qty) as ondemand_cnt 
from table
where reservation = 'ondemand'
group by zone, type, os
) as o
join
(
select zone, type, os, sum(qty) as reserved_cnt
from table
where reservation = 'reserved'
group by zone, type, os
) as r on (o.zone = r.zone and o.type = r.type and o.os = r.os)