id | year | month | category | value
1 2019 01 apple 3
1 2018 12 apple 2
1 2019 01 carrot 4
在此示例中,预期结果是:
category | last month | gain or loss % | gain or loss
apple 2019-01 +50% +1
carrot 2019-01 +100% +4 // Note: no carrot value on previous month
是否有任何方法可以执行此操作而无需进行任何昂贵的连接?
答案 0 :(得分:0)
如果运行的是MySQL 8.0,则可以使用窗口函数和聚合:
select
category,
max(case when rn = 1 then concat(year, '-', month)) last_month,
coalesce(
(
max(case when rn = 1 then value end)
- max(case when rn = 2 then value end)
)
/ max(case when rn = 2 then value end),
1) gain_or_loss_ratio,
max(case when rn = 1 then value end)
- coalesce(max(case when rn = 2 then value end), 0) gain_or_loss
from (
select
t.*,
row_number() over(partition by category order by year desc, month desc) rn
from mytable t
) t
where rn in (1, 2)
group by category
这使您可以比较每个类别的最后2个值,这就是我对您的问题的理解方式。第三列包含一个介于0到1之间的值,而不是一个百分比,我发现它更有用(您可以在应用程序端根据需要设置其格式)。
您可以通过添加一级嵌套来缩短算术表达式,如下所示:
select
category,
last_month,
coalesce((last_value1 - last_value2) / last_value2, 1) gain_or_loss_ratio,
last_value1 - coalesce(last_value2, 0) gain_or_loss
from (
select
category,
max(case when rn = 1 then concat(year, '-', month)) last_month,
max(case when rn = 1 then value end) last_value1,
max(case when rn = 2 then value end) last_value2
from (
select
t.*,
row_number() over(partition by category order by year desc, month desc) rn
from mytable t
) t
where rn in (1, 2)
group by category
) t
答案 1 :(得分:0)
如果您没有中间月份缺失的情况,那么一个简单的滞后工作(以及一些过滤):
public class myClass{
public static string networkHandler(string s) { //static method
try {
string ss = s;
}
catch(string s) {
//handle error
}
}
}
如果您特别想在数据中指定最近的月份而不指定它,也可以使用select category, concat_ws('-', year, month),
coalesce(val / prev_value, 1) as gain_loss_rate,
(val - coalesce(prev_value, 0)) as gain_or_loss
from (select t.*,
lag(value) over (partition by id, category order by year, month) as prev_value
from t
) t
where year = 2019 and month = '01';
:
rank()