简体   繁体   English

两个聚合表上的 Laravel、MYSQL 全连接解决方​​法

[英]Laravel, MYSQL full join workaround on two aggregated tables

I've got a table called transactions with below schema:我有一个名为transactions的表,其架构如下:

TRANSACTIONS
+----+-----------------+-------------------+--------+
| id | to (account_id) | from (account_id) | amount |
+----+-----------------+-------------------+--------+
| 1  | 1               | 3                 | 500    |
+----+-----------------+-------------------+--------+
| 2  | 2               | 1                 | 250    |
+----+-----------------+-------------------+--------+
| 3  | 1               | 2                 | 100    |
+----+-----------------+-------------------+--------+
| 4  | 4               | 2                 | 50     |
+----+-----------------+-------------------+--------+

to and from are foreign keys to id on table accounts . tofrom是表accountsid外键。

I wanna get the subtraction of sum of all received transactions from all paid transactions of selected accounts as in the example accounts 1 and 2 and all the accounts which whom those had transaction with .我想从selected accounts all paid transactionssubtraction all received transactions sum ,如示例账户12以及all the accounts which whom those had transaction with .

This is the desired result:这是想要的结果:

DESIRED QUERY RESULT
+---+------------+---------------+-----------+---------+
| # | account_id | totalReceived | totalPaid | balance |
+---+------------+---------------+-----------+---------+
| 1 | 1          | 600           | 250       | 350     |
+---+------------+---------------+-----------+---------+
| 2 | 2          | 250           | 150       | 100     |
+---+------------+---------------+-----------+---------+
| 3 | 3          | 0             | 500       | -500    |
+---+------------+---------------+-----------+---------+
| 4 | 4          | 50            | 0         | 50      |
+---+------------+---------------+-----------+---------+

What I've got so far:到目前为止我所得到的:

as I'm using Laravel with query builder I run it like follows:当我将 Laravel 与查询构建器一起使用时,我按如下方式运行它:

$k = [1, 2];

$receivedTransactions = DB::table('transactions as t1')->selectRaw('t1.to as account_id, sum(t1.amount) as totalReceived')
    ->whereIn('t1.from', $k)->orWhereIn('t1.to', $k)->groupBy('t1.to');

$paidTransactions = DB::table('transactions as t2')->selectRaw('t2.from as account_id, sum(t2.amount) as totalPaid')
    ->whereIn('t2.from', $k)->orWhereIn('t2.to', $k)->groupBy('t2.from');

$result = $receivedTransactions->leftJoinSub($paidTransactions, 't2', function ($join) {
    $join->on('t1.to', 't2.account_id');
})->selectRaw('totalPaid, (COALESCE(sum(t1.amount),0) - COALESCE(totalPaid,0)) as balance');

The big problem is it doesn't give me the 3rd row in the desired result table, because I don't have full join and I don't get the result from the right table which doesn't have corresponding row in the join so null .最大的问题是它没有给我所需结果表中的第 3 行,因为我没有完全连接,而且我没有从正确的表中获得结果,该表在连接中没有相应的行,所以null

this is what I get:这就是我得到的:

CURRENT QUERY RESULT
+---+------------+---------------+-----------+---------+
| # | account_id | totalReceived | totalPaid | balance |
+---+------------+---------------+-----------+---------+
| 1 | 1          | 600           | 250       | 350     |
+---+------------+---------------+-----------+---------+
| 2 | 2          | 250           | 150       | 100     |
+---+------------+---------------+-----------+---------+
| 4 | 4          | 50            | 0         | 50      |
+---+------------+---------------+-----------+---------+

I don't get the account_id 3 which was involved in giving account 1 the transaction no.1我没有得到 account_id 3参与给账户1的交易 1

Any help would be really appreciated.任何帮助将非常感激。 It doesn't matter if it is in Raw MYSQL format or laravel query builder.它是原始 MYSQL 格式还是 laravel 查询构建器都没有关系。 Thank you very much.非常感谢。

I did this directly on mysql and after I tried to translate to Laravel syntax我直接在 mysql 上做了这个,在我尝试翻译成 Laravel 语法之后

SELECT
  DISTINCT base_accounts.account_id,
  COALESCE(t1.totalReceived, 0) as totalReceived,
  COALESCE(t2.totalPaid, 0) AS totalPaid,
  COALESCE(t1.totalReceived, 0) - COALESCE(t2.totalPaid, 0) as totalBalance
FROM (
     SELECT `to` as account_id FROM transactions UNION SELECT `from` FROM transactions
) as base_accounts
LEFT JOIN (
     SELECT `to` as account_id, sum(amount) as totalReceived FROM transactions GROUP BY `to`
) as t1 on base_accounts.account_id = t1.account_id
LEFT JOIN (
     SELECT `from` as account_id, sum(amount) as totalPaid FROM transactions GROUP BY `from`
) as t2 on base_accounts.account_id = t2.account_id
ORDER BY base_accounts.account_id

在此处输入图片说明

 \DB::table(\DB::raw('(SELECT `to` as account_id FROM transactions UNION SELECT `from` FROM transactions) as base_accounts'))
        ->select(DB::raw('
        DISTINCT base_accounts.account_id,
        COALESCE(t1.totalReceived, 0) as totalReceived,
        COALESCE(t2.totalPaid, 0) AS totalPaid,
        COALESCE(t1.totalReceived, 0) - COALESCE(t2.totalPaid, 0) as totalBalance
        '))
        ->leftJoin(
            \DB::raw('(SELECT `to` as account_id, sum(amount) as totalReceived FROM transactions GROUP BY `to`) as t1'),
            'base_accounts.account_id',
            '=',
            't1.account_id'
        )
        ->leftJoin(
            \DB::raw('(SELECT `from` as account_id, sum(amount) as totalPaid FROM transactions GROUP BY `from`) as t2'),
            'base_accounts.account_id',
            '=',
            't2.account_id'
        )->orderBy('base_accounts.account_id')->get();

I tested the query and worked fine.我测试了查询并且工作正常。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM