SQL Query查找最近的记录是否都是相同的类型

时间:2014-01-24 15:20:23

标签: mysql

我有一个transaction表格,其格式类似于

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越高,事务越新(或者你可以假设有一个created_at列)。

在上述情况下,唯一应返回的order_id为11,因为虽然order_id 5有3个已拒绝的交易,但最近的3个交易为D P D

使用在合理的时间内运行的纯sql是否有一种干净的方法(假设约50M行)。

3 个答案:

答案 0 :(得分:1)

根本不是一个快速的解决方案,但它应该给你你想要的东西(我假设最近的交易是具有更高id列的交易):

SELECT * FROM 
    (
    SELECT  *,
     (
        SELECT COUNT(1) 
        FROM `transaction` a WHERE a.order_id = b.order_id AND
        a.id >= b.id 
     )as num
    FROM `transaction`b
    ) a WHERE num =3
    AND NOT EXISTS
      (
       SELECT NULL FROM `transaction` b where response<>'declined' 
       and b.order_id = a.order_id and b.id >=a.id
      )

答案 1 :(得分:1)

假设越高越近:

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);

答案 2 :(得分:0)

这是一种方式......

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;

小提琴:http://www.sqlfiddle.com/#!2/386aa3/1

只是一个想法......这是否有效(未经测试)......

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);