Mysql SQL查询以查找最近的记录是否都属于同一类型
我有一个事务表,其模式如下Mysql SQL查询以查找最近的记录是否都属于同一类型,mysql,Mysql,我有一个事务表,其模式如下 id | order_id | response | amount 1 | 2 |'payment' | 1000 2 | 5 |'declined'| 0 3 | 5 |'declined'| 0 4 | 5 |'payment' | 500 5 | 5 |'declined'| 0 6 | 11 |'declined'| 0 7 | 11 |'decline
id | order_id | response | amount
1 | 2 |'payment' | 1000
2 | 5 |'declined'| 0
3 | 5 |'declined'| 0
4 | 5 |'payment' | 500
5 | 5 |'declined'| 0
6 | 11 |'declined'| 0
7 | 11 |'declined'| 0
9 | 11 |'declined'| 0
我想做的是找到所有订单,其中该订单最近的三笔交易被“拒绝”。假设id越高,事务越近,或者可以假设在列中创建了一个_
在上述情况下,应该返回的唯一订单号是11,因为订单号5有3个拒绝的交易,最近的3个交易是D p D
有没有一种干净的方法可以让纯sql在合理的大约50万行时间内运行。根本不是一个快速的解决方案,但它应该能满足您的需要我假设最近的事务是id列值较高的事务:
假设id越高,则最近的id越高:
SELECT t0.order_id
FROM transaction t0
JOIN transaction t1 ON
((t1.response=t0.response) AND (t1.order_id=t0.order_id) AND
t1.id=(SELECT MAX(id) FROM transaction WHERE id<t0.id and t0.order_id=order_id))
JOIN transaction t2 ON
((t2.response=t0.response) AND (t2.order_id=t0.order_id) AND
t2.id=(SELECT MAX(id) FROM transaction WHERE id<t1.id AND t0.order_id=order_id))
WHERE t0.response='declined' AND
t0.id=(SELECT MAX(id) FROM transaction WHERE order_id=t0.order_id);
这里有一个方法
SELECT DISTINCT a.order_id
FROM
( SELECT x.*
, COUNT(*) rank
FROM my_table x
JOIN my_table y
ON y.order_id = x.order_id
AND y.id >= x.id
GROUP
BY id HAVING COUNT(*) <= 3
) a
LEFT
JOIN
( SELECT x.*
, COUNT(*) rank
FROM my_table x
JOIN my_table y
ON y.order_id = x.order_id
AND y.id >= x.id
GROUP
BY id HAVING COUNT(*) <= 3
) b
ON b.order_id = a.order_id
AND b.response <> 'declined'
WHERE b.id IS NULL;
表中的记录似乎没有在任何地方记录时间戳。。。您建议如何确定哪些是最新的?…并添加更多样本数据。在开发查询时,您希望确保它涵盖所有情况,对吗?因此,您的示例数据应该至少包含正确查询返回的数据。我编辑了该问题,以便您可以假设有一个created_at列或id列随时间单调增加。这对解决方案应该没有多大区别。这太慢了,我不确定我是否能够验证它是否正确。是的,它可能很慢。对此很抱歉-也不太确定当结果少于3个时该怎么办,但所有结果都已被拒绝。请注意,此解决方案将从order_id上的复合索引中略微受益,响应-但当结果少于3个时,它仍然不知道该怎么办,因为你没有说这很好,并且可以立即运行。唯一的缺点是它不是很灵活,因为如果你想搜索4次拒绝,你必须编写一个新的查询。你是对的。但它可以很容易地扩展:。。。在t3.response=t0.response和t3.order_id=t0.order_id和t3.id=SELECT MAXid FROM transaction,其中idI确认这会给出正确的结果。问题是它有点慢。返回大约50行需要几分钟的时间。作为参考,此查询首先为每个事务分配最近性,然后限制为最近的第三个事务。where子句随后验证所有更新或等于第三个最近交易的交易是否被“拒绝”。这是一个聪明的解决方案,其中3参数是灵活的,并且易于修改。不幸的是,它有点慢,但是一个非常聪明的方法是一种有趣的技术。谢谢你花时间回答,我确实学到了一些东西。
SELECT DISTINCT a.order_id
FROM
( SELECT x.*
, COUNT(*) rank
FROM my_table x
JOIN my_table y
ON y.order_id = x.order_id
AND y.id >= x.id
GROUP
BY id HAVING COUNT(*) <= 3
) a
LEFT
JOIN
( SELECT x.*
, COUNT(*) rank
FROM my_table x
JOIN my_table y
ON y.order_id = x.order_id
AND y.id >= x.id
GROUP
BY id HAVING COUNT(*) <= 3
) b
ON b.order_id = a.order_id
AND b.response <> 'declined'
WHERE b.id IS NULL;
SELECT DISTINCT x.order_id
FROM my_table x
JOIN my_table y
ON y.order_id = x.order_id
AND y.id >= x.id
GROUP
BY x.id
HAVING COUNT(*) = 3
AND COUNT(*) = SUM(CASE WHEN y.response = 'declined' THEN 1 ELSE 0 END);