表 payment_transaction
+----+---------+--------+------------+
| ID | user_id | status | time_stamp |
+----+---------+--------+------------+
| 1 | 1 | 1 | 1414541884 |
| 2 | 2 | 0 | 1414576722 |
| 3 | 2 | 0 | 1414577273 |
| 4 | 3 | 0 | 1414782966 |
| 5 | 3 | 1 | 1414785691 |
| 6 | 4 | 0 | 1415112933 |
+----+---------+--------+------------+
此表存储所有付款交易。 status = 0
表示付款失败,无论出于何种原因,status = 1
表示付款成功。
我现在想设置一个cronjob,所有用户都会在过去7天内收到无法购买会员资格的消息。与上面的示例表中一样,我只需要2行,其中包含最近付款的user_id
,transaction_id
和最近付款的time_stampe
。由于user_id = 3
在首次付款失败后成功获得会员资格,因此应将其排除在外:
+---------+----------------+------------+
| user_id | transaction_id | time_stamp |
+---------+----------------+------------+
| 2 | 3 | 1414577273 |
| 4 | 6 | 1415112933 |
+---------+----------------+------------+
是否可以在一个查询中完成所有这些操作?如果是,它比使用两个查询更有效吗?
到目前为止我得到了什么:
SELECT DISTINCT
`t`.`user_id`,
`t`.`id` AS `transaction_id`,
`t`.`time_stamp`
FROM `payment_transaction` AS `t`
WHERE
`t`.`status` = 0
AND `t`.`time_stamp` < UNIX_TIMESTAMP() - 60*60*24*7
ORDER BY
`t`.`id`
但是,它不会将用户user_id = 3
排除在外,而且还会向我提供首次付款失败,而不是最近的付款。
----编辑----
感谢RST在下面的评论中提供解决方案。经过一些额外的更改后,最终查询如下所示:
SELECT
`t`.`user_id`,
MAX(`t`.`id`) AS `transaction_id`,
MAX(`t`.`time_stamp`) AS `time_stamp`
FROM `payment_transaction` AS `t`
WHERE
`t`.`status` = 0
AND `t`.`time_stamp` < UNIX_TIMESTAMP() - 60*60*24*7
AND `t`.`user_id` NOT IN (
SELECT `user_id`
FROM `payment_transaction`
WHERE `status` = 1
AND UNIX_TIMESTAMP(`time_stamp`) < UNIX_TIMESTAMP() - 60*60*24*7
)
GROUP BY
`t`.`user_id`
ORDER BY
`t`.`id`
答案 0 :(得分:0)
稍微偏离您的请求,但仍应获得相同的结果,具体取决于您对应用程序进行编码的方式。假设最新交易与最准确的交易最相关吗?
如果是这样,您可以查看以下内容(未经测试):
SELECT DISTINCT
`t`.`user_id`,
`t`.`id` AS `transaction_id`,
`t`.`time_stamp`
FROM `payment_transaction` AS `t`
WHERE
`t`.`time_stamp` < UNIX_TIMESTAMP() - 60*60*24*7
GROUP BY
`t`.`user_id`
ORDER BY
`t`.`id`
请注意我没有测试过这个SQL,因为我离开了我的开发机器。我建议您仔细查看GROUP BY命令的复杂性,以确保您不会遇到一些未捕获的边缘情况。
答案 1 :(得分:0)
DROP TABLE IF EXISTS payment_transaction;
CREATE TABLE payment_transaction
(ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY
,user_id INT NOT NULL
,status INT NOT NULL
,time_stamp BIGINT NOT NULL
);
INSERT INTO payment_transaction VALUES
(1 ,1 ,1 ,1414541884),
(2 ,2 ,0 ,1414576722),
(3 ,2 ,0 ,1414577273),
(4 ,3 ,0 ,1414782966),
(5 ,3 ,1 ,1414785691),
(6 ,4 ,0 ,1415112933);
SELECT x.*
FROM payment_transaction x
JOIN
( SELECT a.user_id
, MAX(a.id) max_id
FROM payment_transaction a
LEFT
JOIN payment_transaction b
ON b.user_id = a.user_id
AND b.status = 1
AND b.time_stamp > a.time_stamp
WHERE a.time_stamp > UNIX_TIMESTAMP(NOW())-604800
AND a.status = 0
AND b.id IS NULL
) y
ON y.user_id = x.user_id
AND y.max_id = x.id;
+----+---------+--------+------------+
| ID | user_id | status | time_stamp |
+----+---------+--------+------------+
| 6 | 4 | 0 | 1415112933 |
+----+---------+--------+------------+