我有一张包含交易的表:
Transactions
------------
id | account | type | date_time | amount
----------------------------------------------------
1 | 001 | 'R' | '2012-01-01 10:01:00' | 1000
2 | 003 | 'R' | '2012-01-02 12:53:10' | 1500
3 | 003 | 'A' | '2012-01-03 13:10:01' | -1500
4 | 002 | 'R' | '2012-01-03 17:56:00' | 2000
5 | 001 | 'R' | '2012-01-04 12:30:01' | 1000
6 | 002 | 'A' | '2012-01-04 13:23:01' | -2000
7 | 003 | 'R' | '2012-01-04 15:13:10' | 3000
8 | 003 | 'R' | '2012-01-05 12:12:00' | 1250
9 | 003 | 'A' | '2012-01-06 17:24:01' | -1250
我希望选择所有特定类型(“R”),但不选择那些立即(按日期时间字段的顺序)为同一帐户提交另一种类型(“A”)的交易...
因此,根据前面的示例,查询应抛出以下行:
id | account |type | date | amount
----------------------------------------------------
1 | 001 | 'R' | '2012-01-01 10:01:00' | 1000
5 | 001 | 'R' | '2012-01-04 12:30:01' | 1000
7 | 003 | 'R' | '2012-01-04 15:13:10' | 3000
(如您所见,第 2 行未显示,因为第 3 行“取消”了它...第 4 行也被第 6 行“取消”;第 7 行确实出现(即使帐户 003 属于已取消的第 2 行) ,这次在第 7 行中,它没有被任何“A”行取消);并且第 8 行不会出现(对于 003 帐户来说也是如此,因为现在这个被 9 取消了,这也没有取消 7,只是上一个)一:8...
我已经尝试过连接、Where 子句中的子查询,但我真的不确定如何进行查询...
我尝试过的:
尝试加入:
SELECT trans.type as type,
trans.amount as amount,
trans.date_time as dt,
trans.account as acct,
FROM Transactions trans
INNER JOIN ( SELECT t.type AS type, t.acct AS acct, t.date_time AS date_time
FROM Transactions t
WHERE t.date_time > trans.date_time
ORDER BY t.date_time DESC
) AS nextTrans
ON nextTrans.acct = trans.acct
WHERE trans.type IN ('R')
AND nextTrans.type NOT IN ('A')
ORDER BY DATE(trans.date_time) ASC
这会引发错误,因为我无法将外部值引入 MySQL 中的 JOIN。
在其中尝试子查询:
SELECT trans.type as type,
trans.amount as amount,
trans.date_time as dt,
trans.account as acct,
FROM Transactions trans
WHERE trans.type IN ('R')
AND trans.datetime <
( SELECT t.date_time AS date_time
FROM Transactions t
WHERE t.account = trans.account
ORDER BY t.date_time DESC
) AS nextTrans
ON nextTrans.acct = trans.acct
ORDER BY DATE(trans.date_time) ASC
这是错误的,我可以将外部值引入 MySQL 中的 WHERE,但我无法找到正确过滤我需要的方法......
重要编辑:
我设法实现了一个解决方案,但现在需要认真优化。这里是:
SELECT *
FROM (SELECT t1.*, tFlagged.id AS cancId, tFlagged.type AS cancFlag
FROM transactions t1
LEFT JOIN (SELECT t2.*
FROM transactions t2
ORDER BY t2.date_time ASC ) tFlagged
ON (t1.account=tFlagged.account
AND
t1.date_time < tFlagged.date_time)
WHERE t1.type = 'R'
GROUP BY t1.id) tCanc
WHERE tCanc.cancFlag IS NULL
OR tCanc.cancFlag <> 'A'
我将表本身加入进来,只是考虑到相同的帐户和很棒的日期时间。连接按 date_time 排序。按 id 分组我设法只获得连接的第一个结果,这恰好是同一帐户的下一笔交易。
然后在外部选择上,我过滤掉那些具有“A”的交易,因为这意味着下一个交易实际上是对其的取消。换句话说,如果同一账户没有下一笔交易或者下一笔交易是“R”,那么它不会被取消,并且必须显示在结果中......
我懂了:
+----+---------+------+---------------------+--------+--------+----------+
| id | account | type | date_time | amount | cancId | cancFlag |
+----+---------+------+---------------------+--------+--------+----------+
| 1 | 001 | R | 2012-01-01 10:01:00 | 1000 | 5 | R |
| 5 | 001 | R | 2012-01-04 12:30:01 | 1000 | NULL | NULL |
| 7 | 003 | R | 2012-01-04 15:13:10 | 3000 | 8 | R |
+----+---------+------+---------------------+--------+--------+----------+
它将同一帐户的每笔交易及时与下一笔交易联系起来,然后过滤掉那些已取消的交易......成功!
正如我所说,现在的问题是优化。我的真实数据有很多行(因为随着时间的推移保存事务的表预计会有),对于现在大约 10,000 行的表,我在 1 分钟 44 秒内通过此查询得到了肯定的结果。我想这就是连接的问题...(对于那些知道这里协议的人,我应该做什么?在这里提出一个新问题并将其作为该问题的解决方案发布?或者只是在这里等待更多答案?)