如何显示从变量键列中获取的累积键=值?

问题描述 投票:0回答:2

我有一个具有以下结构的MySQL

transfers
表:

CREATE TABLE `transfers` (
 `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
 `id_account_destination` bigint(20) unsigned NOT NULL,
 `id_account_origin` bigint(20) unsigned NOT NULL,
 `amount` decimal(10, 2) signed NOT NULL DEFAULT 0,
 `created_at` datetime DEFAULT CURRENT_TIMESTAMP,

 PRIMARY KEY (`id`),
 KEY `id_account_destination` (`id_account_destination`),
 KEY `id_account_origin` (`id_account_origin`),
 KEY `created_at` (`created_at`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

显然,这张表存储转账。它记录了transferamount和涉及的两个accountorigindestination

我需要的是创建一个

SELECT
报表,该报表从一个时期(由 created_at 过滤)获取所有给定的
transfers
,并显示所有当前账户在该部分中有多少收入和结果。像这样的东西:

+------------+---------------+-----------------|
| id_account | income_amount | outcome_ammount |
+------------+---------------+-----------------|
|         19 |     27690.87  |        57204.80 |
|        112 |      1000.00  |         2349.00 |
|       1011 |    575877.56  |        17454.50 |
|         17 |    135002.61  |          204.30 |
+------------+---------------+-----------------|

这里的难点在于

id_account
列将从任何传输中获取
id_account_origin
id_account_destination
并通过其余传输找到所有其他事件。如果在“origin”位置找到账户,转账的amount会添加到
outcome_ammount
栏;但如果在“目标”位置找到该帐户,则应将转账的amount添加到
income_ammount
列。

所以输出表与传输表完全不同,尽管所有需要的信息都已经存在了。

到目前为止,我所取得的成就是仅以一种方式获取该信息:

SELECT
    id_account_origin,
    SUM(t.amount) AS outcome_amount
FROM transfers t
GROUP BY t.id_account_origin;

哪个返回:

+-------------------+----------------+
| id_account_origin | outcome_amount |
+-------------------+----------------+
|             10009 |     2761390.87 |
|             10012 |        1000.00 |
|             10011 |      575877.56 |
|             10007 |      135002.61 |
+-------------------+----------------+

而且比上面预期的交叉列要容易得多。

sql mysql aggregate-functions unpivot
2个回答
1
投票

id_account_destination
写另一个查询。然后将它们与
UNION
结合起来以取消旋转。

SELECT id_account, SUM(outcome_amount) AS outcome_amount, SUM(income_amount) AS income_amount
FROM (
    SELECT id_account_origin AS id_account, SUM(t.amount) AS outcome_amount, 0 AS income_amount
    FROM transfers t
    GROUP BY id_account
    UNION ALL
    SELECT id_account_destination AS id_account, 0 AS outcome_amount, SUM(-t.amount) AS income_amount
    FROM transfers t
    GROUP BY id_account
) AS x 
GROUP BY id_account

1
投票

一种方法是反透视数据,然后聚合。

在最近的 MySQL 版本中,我们可以使用横向连接,这避免了两次扫描表

union all

select x.id_account, 
    sum(x.income_amount) income_amount, 
    sum(x.outcome_amount) outcome_amount
from transfers t
cross join lateral (
    select t.id_account_destination, t.amount, 0 
    union all select t.id_account_origin, 0, t.amount
) x(id_account, income_amount, outcome_amount)
group by x.id_account

参考:MySQL - 如何将列转为行?

这里是一个小演示.

样本数据:

id id_account_destination id_account_origin 数量 创建于
1 1 2 100.00 2023-05-04 19:59:37
2 1 3 50.00 2023-05-04 19:59:37
3 4 1 30.00 2023-05-04 19:59:37

结果:

id_account 收入_金额 结果_金额
1 150.00 30.00
2 0.00 100.00
3 0.00 50.00
4 30.00 0.00
© www.soinside.com 2019 - 2024. All rights reserved.