Php 如何构建一个查询,对交换发件人和收件人的交易余额进行求和
我正在设置一个脚本,它只使用一个事务表而不使用余额表来计算用户的余额。现在我想试着做一个这样的查询,这可能吗?如果可能,我该怎么做 这适用于使用现有代码库/数据库的内部应用程序。目前,我只使用php完成了这项工作Php 如何构建一个查询,对交换发件人和收件人的交易余额进行求和,php,mysql,sql,Php,Mysql,Sql,我正在设置一个脚本,它只使用一个事务表而不使用余额表来计算用户的余额。现在我想试着做一个这样的查询,这可能吗?如果可能,我该怎么做 这适用于使用现有代码库/数据库的内部应用程序。目前,我只使用php完成了这项工作 $outgoing = $this->entityManager->getRepository(Transaction::class)->findBy([ 'sender' => $user, 'contract' => $contract
$outgoing = $this->entityManager->getRepository(Transaction::class)->findBy([
'sender' => $user,
'contract' => $contract
]);
$incoming = $this->entityManager->getRepository(Transaction::class)->findBy([
'recipient' => $user,
'contract' => $contract
]);
$history = $outgoing + $incoming;
foreach ($history as $index => $transaction) {
if ($transaction->getTokens() > 0) {
continue;
}
unset($history[$index]);
}
usort($history, function ($a, $b) {
if ($a->getCreatedOn() === $b->getCreatedOn()) {
return 0;
}
return $a->getCreatedOn() > $b->getCreatedOn() ? 1 : -1;
});
$balance = 0;
foreach ($history as $row) {
if ($row->getSender() === $user) {
$balance -= $row->getTokens();
}
if ($row->getRecipient() === $user) {
$balance += $row->getTokens();
}
}
return $balance;
表的结构:
交易
- 身份证
- 发送者身份证
- 收件人id
- 合同编号
- 代币
- 价格
- 创建于
我希望使用一个int作为余额编号。我不知道如何将其转换为对entitymanager接口的调用,但以下是一些SQL,它们应该可以完成这项工作,并且非常容易阅读:
SELECT credits.total - debits.total AS balance
FROM
(SELECT SUM(tokens) AS total
FROM `transaction`
WHERE sender_id = :user
AND contract_id = :contract) AS debits
CROSS JOIN
(SELECT SUM(tokens) AS total
FROM `transaction`
WHERE recipient_id = :user
AND contract_id = :contract) AS credits
您应该拥有以下两个索引,以优化此功能:
(发件人id、合同id、代币)
(收件人id、合同id、代币)
CREATE TABLE `transaction` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`sender_id` int(11) NOT NULL,
`recipient_id` int(11) NOT NULL,
`contract_id` int(11) NOT NULL,
`tokens` int(11) NOT NULL,
`price` decimal(9,2) NOT NULL,
`created_on` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `sender_id` (`sender_id`,`contract_id`,`tokens`),
KEY `recipient_id` (`recipient_id`,`contract_id`,`tokens`)
);
下面是一些示例数据。两个借项和三个贷项,每笔交易中有三个代币:
INSERT INTO `transaction` VALUES
(1,10,20,1,3,19.95,'2019-01-20 15:41:47'),
(2,10,20,1,3,19.95,'2019-01-20 15:41:47'),
(3,30,10,1,3,19.95,'2019-01-20 15:41:47'),
(4,30,10,1,3,19.95,'2019-01-20 15:41:47'),
(5,20,10,1,3,19.95,'2019-01-20 15:41:47');
下面是查询解释报告,显示了每个子查询中覆盖索引的使用情况:
+----+-------------+-------------+--------+---------------+--------------+---------+-------------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------------+--------+---------------+--------------+---------+-------------+------+-------------+
| 1 | PRIMARY | <derived2> | system | NULL | NULL | NULL | NULL | 1 | NULL |
| 1 | PRIMARY | <derived3> | system | NULL | NULL | NULL | NULL | 1 | NULL |
| 3 | DERIVED | transaction | ref | recipient_id | recipient_id | 8 | const,const | 3 | Using index |
| 2 | DERIVED | transaction | ref | sender_id | sender_id | 8 | const,const | 2 | Using index |
+----+-------------+-------------+--------+---------------+--------------+---------+-------------+------+-------------+
我添加了表结构和我想要的输出。
+---------+
| balance |
+---------+
| 3 |
+---------+