mysql – SQL:选择行不在同一个表中的条件的事务

前端之家收集整理的这篇文章主要介绍了mysql – SQL:选择行不在同一个表中的条件的事务前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

我有一个交易表:

  1. Transactions
  2. ------------
  3. id | account | type | date_time | amount
  4. ----------------------------------------------------
  5. 1 | 001 | 'R' | '2012-01-01 10:01:00' | 1000
  6. 2 | 003 | 'R' | '2012-01-02 12:53:10' | 1500
  7. 3 | 003 | 'A' | '2012-01-03 13:10:01' | -1500
  8. 4 | 002 | 'R' | '2012-01-03 17:56:00' | 2000
  9. 5 | 001 | 'R' | '2012-01-04 12:30:01' | 1000
  10. 6 | 002 | 'A' | '2012-01-04 13:23:01' | -2000
  11. 7 | 003 | 'R' | '2012-01-04 15:13:10' | 3000
  12. 8 | 003 | 'R' | '2012-01-05 12:12:00' | 1250
  13. 9 | 003 | 'A' | '2012-01-06 17:24:01' | -1250

并且我希望选择所有特定类型(‘R’),但不是那些立即(按照date_time字段的顺序)为同一帐户提交的另一种类型(‘A’)的另一个交易…

因此,在前面的示例中,查询应抛出以下行:

  1. id | account |type | date | amount
  2. ----------------------------------------------------
  3. 1 | 001 | 'R' | '2012-01-01 10:01:00' | 1000
  4. 5 | 001 | 'R' | '2012-01-04 12:30:01' | 1000
  5. 7 | 003 | 'R' | '2012-01-04 15:13:10' | 3000

(如您所见,第2行未显示,因为第3行’取消’它…第4行’第4行被’取消’;行7确实出现(即使帐户003属于已取消的第2行),这次在第7行,它没有被任何’A’行取消;并且第8行也不会出现(它也是003帐户,因为现在这个被9取消,这也不会取消7,只是前一个一:8 ……

我在Where子句中尝试了Joins,子查询,但我真的不确定如何进行查询

我尝试过的:

尝试加入:

  1. SELECT trans.type as type,trans.amount as amount,trans.date_time as dt,trans.account as acct,FROM Transactions trans
  2. INNER JOIN ( SELECT t.type AS type,t.acct AS acct,t.date_time AS date_time
  3. FROM Transactions t
  4. WHERE t.date_time > trans.date_time
  5. ORDER BY t.date_time DESC
  6. ) AS nextTrans
  7. ON nextTrans.acct = trans.acct
  8. WHERE trans.type IN ('R')
  9. AND nextTrans.type NOT IN ('A')
  10. ORDER BY DATE(trans.date_time) ASC

这会引发错误,因为我无法将外部值引入MysqL中的JOIN.

在以下位置尝试子查询

  1. SELECT trans.type as type,FROM Transactions trans
  2. WHERE trans.type IN ('R')
  3. AND trans.datetime <
  4. ( SELECT t.date_time AS date_time
  5. FROM Transactions t
  6. WHERE t.account = trans.account
  7. ORDER BY t.date_time DESC
  8. ) AS nextTrans
  9. ON nextTrans.acct = trans.acct
  10. ORDER BY DATE(trans.date_time) ASC

这是错误的,我可以将外部值引入MysqL中的WHERE,但我无法找到正确过滤我需要的方法

重要编辑:

我设法实现了解决方案,但现在需要认真优化.这里是:

  1. SELECT *
  2. FROM (SELECT t1.*,tFlagged.id AS cancId,tFlagged.type AS cancFlag
  3. FROM transactions t1
  4. LEFT JOIN (SELECT t2.*
  5. FROM transactions t2
  6. ORDER BY t2.date_time ASC ) tFlagged
  7. ON (t1.account=tFlagged.account
  8. AND
  9. t1.date_time < tFlagged.date_time)
  10. WHERE t1.type = 'R'
  11. GROUP BY t1.id) tCanc
  12. WHERE tCanc.cancFlag IS NULL
  13. OR tCanc.cancFlag <> 'A'

我自己加入了这个表,只考虑了相同的帐户和很棒的date_time. Join按date_time排序.按ID分组我设法只获得了连接的第一个结果,这恰好是同一帐户的下一个事务.

然后在外部选择上,我过滤掉那些具有“A”的东西,因为这意味着下一个交易实际上是对它的取消.换句话说,如果同一个帐户没有下一个交易,或者下一个交易是’R’,那么它不会被取消,并且必须在结果中显示

我懂了:

  1. +----+---------+------+---------------------+--------+--------+----------+
  2. | id | account | type | date_time | amount | cancId | cancFlag |
  3. +----+---------+------+---------------------+--------+--------+----------+
  4. | 1 | 001 | R | 2012-01-01 10:01:00 | 1000 | 5 | R |
  5. | 5 | 001 | R | 2012-01-04 12:30:01 | 1000 | NULL | NULL |
  6. | 7 | 003 | R | 2012-01-04 15:13:10 | 3000 | 8 | R |
  7. +----+---------+------+---------------------+--------+--------+----------+

它将每个交易与下一个交易关联到同一个帐户,然后筛选出已取消的交易…成功!!

正如我所说,现在的问题是优化.我的真实数据有很多行(因为预计会有时间跨越事务的表),而对于现在约有10,000行的表,我在1分44秒内得到了一个积极的结果.我想这就是加入的东西……(对于那些在这里知道协议的人,我该怎么做?在这里发一个新问题并将其作为解决方案发布到这个?或者只是在这里等待更多答案?)

最佳答案
这是一个基于嵌套子查询解决方案.首先,我添加了几行来捕获更多案例.例如,交易10不应该取消交易10,因为交易11介于两者之间.

  1. > select * from transactions order by date_time;
  2. +----+---------+------+---------------------+--------+
  3. | id | account | type | date_time | amount |
  4. +----+---------+------+---------------------+--------+
  5. | 1 | 1 | R | 2012-01-01 10:01:00 | 1000 |
  6. | 2 | 3 | R | 2012-01-02 12:53:10 | 1500 |
  7. | 3 | 3 | A | 2012-01-03 13:10:01 | -1500 |
  8. | 4 | 2 | R | 2012-01-03 17:56:00 | 2000 |
  9. | 5 | 1 | R | 2012-01-04 12:30:01 | 1000 |
  10. | 6 | 2 | A | 2012-01-04 13:23:01 | -2000 |
  11. | 7 | 3 | R | 2012-01-04 15:13:10 | 3000 |
  12. | 8 | 3 | R | 2012-01-05 12:12:00 | 1250 |
  13. | 9 | 3 | A | 2012-01-06 17:24:01 | -1250 |
  14. | 10 | 3 | R | 2012-01-07 00:00:00 | 1250 |
  15. | 11 | 3 | R | 2012-01-07 05:00:00 | 4000 |
  16. | 12 | 3 | A | 2012-01-08 00:00:00 | -1250 |
  17. | 14 | 2 | R | 2012-01-09 00:00:00 | 2000 |
  18. | 13 | 3 | A | 2012-01-10 00:00:00 | -1500 |
  19. | 15 | 2 | A | 2012-01-11 04:00:00 | -2000 |
  20. | 16 | 2 | R | 2012-01-12 00:00:00 | 5000 |
  21. +----+---------+------+---------------------+--------+
  22. 16 rows in set (0.00 sec)

首先,创建一个查询,为每个事务“获取同一帐户中该事务之前的最近事务的日期”:

  1. SELECT t2.*,MAX(t1.date_time) AS prev_date
  2. FROM transactions t1
  3. JOIN transactions t2
  4. ON (t1.account = t2.account
  5. AND t2.date_time > t1.date_time)
  6. GROUP BY t2.account,t2.date_time
  7. ORDER BY t2.date_time;
  8. +----+---------+------+---------------------+--------+---------------------+
  9. | id | account | type | date_time | amount | prev_date |
  10. +----+---------+------+---------------------+--------+---------------------+
  11. | 3 | 3 | A | 2012-01-03 13:10:01 | -1500 | 2012-01-02 12:53:10 |
  12. | 5 | 1 | R | 2012-01-04 12:30:01 | 1000 | 2012-01-01 10:01:00 |
  13. | 6 | 2 | A | 2012-01-04 13:23:01 | -2000 | 2012-01-03 17:56:00 |
  14. | 7 | 3 | R | 2012-01-04 15:13:10 | 3000 | 2012-01-03 13:10:01 |
  15. | 8 | 3 | R | 2012-01-05 12:12:00 | 1250 | 2012-01-04 15:13:10 |
  16. | 9 | 3 | A | 2012-01-06 17:24:01 | -1250 | 2012-01-05 12:12:00 |
  17. | 10 | 3 | R | 2012-01-07 00:00:00 | 1250 | 2012-01-06 17:24:01 |
  18. | 11 | 3 | R | 2012-01-07 05:00:00 | 4000 | 2012-01-07 00:00:00 |
  19. | 12 | 3 | A | 2012-01-08 00:00:00 | -1250 | 2012-01-07 05:00:00 |
  20. | 14 | 2 | R | 2012-01-09 00:00:00 | 2000 | 2012-01-04 13:23:01 |
  21. | 13 | 3 | A | 2012-01-10 00:00:00 | -1500 | 2012-01-08 00:00:00 |
  22. | 15 | 2 | A | 2012-01-11 04:00:00 | -2000 | 2012-01-09 00:00:00 |
  23. | 16 | 2 | R | 2012-01-12 00:00:00 | 5000 | 2012-01-11 04:00:00 |
  24. +----+---------+------+---------------------+--------+---------------------+
  25. 13 rows in set (0.00 sec)

将其用作子查询以使每个事务及其前任在同一行上.使用一些过滤来抽出我们感兴趣的交易 – 即’A’交易,其前身是’R’交易,它们完全取消 –

  1. SELECT
  2. t3.*,transactions.*
  3. FROM
  4. transactions
  5. JOIN
  6. (SELECT t2.*,MAX(t1.date_time) AS prev_date
  7. FROM transactions t1
  8. JOIN transactions t2
  9. ON (t1.account = t2.account
  10. AND t2.date_time > t1.date_time)
  11. GROUP BY t2.account,t2.date_time) t3
  12. ON t3.account = transactions.account
  13. AND t3.prev_date = transactions.date_time
  14. AND t3.type='A'
  15. AND transactions.type='R'
  16. AND t3.amount + transactions.amount = 0
  17. ORDER BY t3.date_time;
  18. +----+---------+------+---------------------+--------+---------------------+----+---------+------+---------------------+--------+
  19. | id | account | type | date_time | amount | prev_date | id | account | type | date_time | amount |
  20. +----+---------+------+---------------------+--------+---------------------+----+---------+------+---------------------+--------+
  21. | 3 | 3 | A | 2012-01-03 13:10:01 | -1500 | 2012-01-02 12:53:10 | 2 | 3 | R | 2012-01-02 12:53:10 | 1500 |
  22. | 6 | 2 | A | 2012-01-04 13:23:01 | -2000 | 2012-01-03 17:56:00 | 4 | 2 | R | 2012-01-03 17:56:00 | 2000 |
  23. | 9 | 3 | A | 2012-01-06 17:24:01 | -1250 | 2012-01-05 12:12:00 | 8 | 3 | R | 2012-01-05 12:12:00 | 1250 |
  24. | 15 | 2 | A | 2012-01-11 04:00:00 | -2000 | 2012-01-09 00:00:00 | 14 | 2 | R | 2012-01-09 00:00:00 | 2000 |
  25. +----+---------+------+---------------------+--------+---------------------+----+---------+------+---------------------+--------+
  26. 4 rows in set (0.00 sec)

从上面的结果可以看出我们几乎就在那里 – 我们已经确定了不需要的交易.使用LEFT JOIN,我们可以从整个事务集中筛选出这些:

  1. SELECT
  2. transactions.*
  3. FROM
  4. transactions
  5. LEFT JOIN
  6. (SELECT
  7. transactions.id
  8. FROM
  9. transactions
  10. JOIN
  11. (SELECT t2.*,MAX(t1.date_time) AS prev_date
  12. FROM transactions t1
  13. JOIN transactions t2
  14. ON (t1.account = t2.account
  15. AND t2.date_time > t1.date_time)
  16. GROUP BY t2.account,t2.date_time) t3
  17. ON t3.account = transactions.account
  18. AND t3.prev_date = transactions.date_time
  19. AND t3.type='A'
  20. AND transactions.type='R'
  21. AND t3.amount + transactions.amount = 0) t4
  22. USING(id)
  23. WHERE t4.id IS NULL
  24. AND transactions.type = 'R'
  25. ORDER BY transactions.date_time;
  26. +----+---------+------+---------------------+--------+
  27. | id | account | type | date_time | amount |
  28. +----+---------+------+---------------------+--------+
  29. | 1 | 1 | R | 2012-01-01 10:01:00 | 1000 |
  30. | 5 | 1 | R | 2012-01-04 12:30:01 | 1000 |
  31. | 7 | 3 | R | 2012-01-04 15:13:10 | 3000 |
  32. | 10 | 3 | R | 2012-01-07 00:00:00 | 1250 |
  33. | 11 | 3 | R | 2012-01-07 05:00:00 | 4000 |
  34. | 16 | 2 | R | 2012-01-12 00:00:00 | 5000 |
  35. +----+---------+------+---------------------+--------+

猜你在找的MySQL相关文章