MySQL对角求和值

MySQL对角求和值,mysql,sql,datetime,recursive-query,metabase,Mysql,Sql,Datetime,Recursive Query,Metabase,我有一张这样的桌子: | created_at | Current_Value | M1 | M2 | M3 | M4 | | ---------- | ------------- | --- | --- | --- | --- | | 01/08/2020 | 840 | 840 | 838 | 838 | 838 | | 01/09/2020 | 65 | 63 | 61 | 59 | 0 | | 01/10/2020 | 109

我有一张这样的桌子:

| created_at | Current_Value | M1  | M2  | M3  | M4  |
| ---------- | ------------- | --- | --- | --- | --- |
| 01/08/2020 | 840           | 840 | 838 | 838 | 838 |
| 01/09/2020 | 65            | 63  | 61  | 59  | 0   |
| 01/10/2020 | 109           | 104 | 99  | 0   | 0   |
| 01/11/2020 | 105           | 100 | 0   | 0   | 0   |
| 01/12/2020 | 61            | 0   | 0   | 0   | 0   |
Current\u Value
列存储在
created\u中创建的项目在
month时的计数,列
M1
-
M4
存储
Current\u Value
值减去接下来几个月中该值相对于
created\u在
月份的减少值,例如,第二行(日期2020年9月1日)中的列
M1
告诉我M1(下个月,2020年10月1日)的值是63,因此它减少了2(65-63),依此类推

现在,我想在Metabase中创建一个聚合报告,显示每月项目数的总体减少情况,即总共一行

现在的问题是,因为我在Metabase中创建这个报表,所以我不能使用存储例程,也不能使用任何其他语言,所以我只能使用基本的MySQL

我需要实现的是对角添加值,因此,例如,我需要执行以下操作:

注意:短语前一行缩写为
pr
,因此更简洁

| created_at | Current_Value | M1            | M2            | M3             | M4  |
| ---------- | ------------- | ------------- | ------------- | -------------- | --- |
| 01/08/2020 | 840           | 840           | 838           | 838            | 838 |
| 01/09/2020 | 65 + M1 in pr | 63 + M2 in pr | 61 + M3 in pr | 59 + M4 in pr  | 0   |
| 01/10/2020 | 109+ M1 in pr | 104+ M2 in pr | 99 + M3 in pr | 0              | 0   |
| 01/11/2020 | 105+ M1 in pr | 100+ M2 in pr | 0             | 0              | 0   |
| 01/12/2020 | 61 + M1 in pr | 0             | 0             | 0              | 0   |
现在在正常情况下,我会使用会话变量来实现这一点,所以我会做如下操作:

(@varM1 :=  0  + @varM1) AS M1_Prev, ( @varM1 := M1) M1_Now
要从上一行获取值,以便将其添加到当前行中,我需要做的不仅仅是从上一行获取值,而是从上一行获取已求和的值,因此我实际需要执行的操作如下:

| created_at | Current_Value | M1  | M2  | M3  | M4  |
| ---------- | ------------- | --- | --- | --- | --- |
| 01/08/2020 | 840           | 840 | 838 | 838 | 838 |
| 01/09/2020 | 65            | 63  | 61  | 59  | 0   |
| 01/10/2020 | 109           | 104 | 99  | 0   | 0   |
| 01/11/2020 | 105           | 100 | 0   | 0   | 0   |
| 01/12/2020 | 61            | 0   | 0   | 0   | 0   |
注意:每个单元格被拉伸到3行,但它仍然只表示一个单元格

| created_at | Current_Value | M1            | M2            | M3             | M4  |
| ---------- | ------------- | ------------- | ------------- | -------------- | --- |
| 01/08/2020 | 840           | 840           | 838           | 838            | 838 |
| ---------- | ------------- | ------------- | ------------- | -------------- | --- |
| 01/09/2020 | 65 + M1 in pr | 63 + M2 in pr | 61 + M3 in pr | 59 + M4 in pr  | 0   |
|            | = 65 + 840    | = 63 + 838    | = 61 + 838    | = 59 + 838     |     |
|            | = 905         | = 901         | = 899         | = 897          |     |
| ---------- | ------------- | ------------- | ------------- | -------------- | --- |
| 01/10/2020 | 109+ M1 in pr | 104+ M2 in pr | 99 + M3 in pr | 0              | 0   |
|            | = 109 + 901   | = 104 + 899   | = 99 + 897    |                |     |
|            | = 1010        | = 1003        | = 996         |                |     |
| ---------- | ------------- | ------------- | ------------- | -------------- | --- |
| 01/11/2020 | 105+ M1 in pr | 100+ M2 in pr | 0             | 0              | 0   |
|            | = 105 + 1003  | = 100 + 996   |               |                |     |
|            | = 1108        | = 1096        |               |                |     |
| ---------- | ------------- | ------------- | ------------- | -------------- | --- |
| 01/12/2020 | 61 + M1 in pr | 0             | 0             | 0              | 0   |
|            | = 61 + 1096   |               |               |                |     |
|            | = 1157        |               |               |                |     |
| ---------- | ------------- | ------------- | ------------- | -------------- | --- |
因此,我需要以相同的表结束,但以这种方式聚合值,以便处理结果

在过去的几个小时里,我一直在为这个问题绞尽脑汁,重新安排并创建新的变量来实现这一点,但不幸的是,我没有成功

这在普通MySQL中可能吗?有可能吗?你能给我指一下正确的方向吗?因为我不幸被卡住了

我使用的是MySQL v5.7


非常感谢

数据模型让事情变得更加困难。尽管使用unpivot/pivot和window函数可能实现这一点,但我发现使用递归查询更容易表达逻辑:

with  recursive
    data as (select t.*, row_number() over(order by created_at) rn from mytable t),
    cte as (
        select rn, created_at, current_value, m1, m2, m3, m4 from data where rn = 1
        union all
        select d.rn, d.created_at,
            d.current_value + c.m1, d.m1 + c.m2, d.m2 + c.m3, d.m3 + c.m4, d.m4
        from cte c
        inner join data d on d.rn = c.rn + 1
    )
select * from cte
这基本上是从最早的日期到最晚的日期遍历数据集,同时根据需要跨行执行计算

rn | created_at | current_value | m1 | m2 | m3 | m4 -: | :--------- | ------------: | ---: | --: | --: | --: 1 | 2020-08-01 | 840 | 840 | 838 | 838 | 838 2 | 2020-09-01 | 905 | 901 | 899 | 897 | 0 3 | 2020-10-01 | 1010 | 1003 | 996 | 0 | 0 4 | 2020-11-01 | 1108 | 1096 | 0 | 0 | 0 5 | 2020-12-01 | 1157 | 0 | 0 | 0 | 0 rn |在|当前|值| m1 | m2 | m3 | m4时创建| -: | :--------- | ------------: | ---: | --: | --: | --: 1 | 2020-08-01 | 840 | 840 | 838 | 838 | 838 2 | 2020-09-01 | 905 | 901 | 899 | 897 | 0 3 | 2020-10-01 | 1010 | 1003 | 996 | 0 | 0 4 | 2020-11-01 | 1108 | 1096 | 0 | 0 | 0 5 | 2020-12-01 | 1157 | 0 | 0 | 0 | 0
请注意,窗口函数仅在MySQL 8.0中可用。

这种问题是架构设计不佳的症状。数据库表不是一个spreadsheet@Strawberry我知道这有点笨重,但是,在Metabase中没有其他方法可以实现,我知道我可能必须在Metabase和MySQL之外以编程方式实现,但我想首先知道是否有某种方法可以在MySQL中实现,或者不可能,所以没有必要尝试。非常感谢,在我的本地DB上测试了这个,它工作起来很有魅力,我没有想到我可以使用CTE,但是正如你在回答中所说,CTE在8.0中可用,我正在使用的数据库是MySQL 5.7,所以这不起作用(我忘了提到这个-我会更新我的问题),你知道有没有其他方法可以达到这个目的?感谢you@Raymond_90:在MySQL 5.7中实现这一点会很乏味。我也这么认为,因此在这种情况下,使用Python/R将是最好的方法。我将尝试使用更多变量来实现这一点,如果我没有成功,我将求助于使用Python/R。所以在v5.7中可能没有简单的解决方案,对吗?嗯,这也是我问题的一个重要答案,非常感谢:-)