从三个月前开始,我想得到每月购买我产品的客户的身份证。今天是2020-02-15。所以我想得到在2019年11月,2019年12月,2020年1月购买的客户。
我只有一个表顺序(mysql),如下所示:
订单表(主键=id(自动递增)):
-----------------------------------------------
| ID | id_cust | buy_date |
-----------------------------------------------
| 1 | 10 | 2019-11-01 |
| 2 | 11 | 2019-11-10 |
| 3 | 10 | 2019-12-11 |
| 4 | 12 | 2019-12-12 |
| 5 | 10 | 2020-01-13 |
| 6 | 11 | 2020-01-14 |
| 7 | 12 | 2020-01-15 |
-----------------------------------------------
根据我的要求,答案是id\u cust 10
我试过了,结果是这样的:
SELECT g1.`id_cust`
FROM `orders` g1
JOIN `orders` g2
ON g2.`id_cust` = g1.`id_cust`
AND g2.`buy_date` >= STR_TO_DATE(CONCAT('01-', LPAD(MONTH(DATE_SUB(NOW(), INTERVAL 2 MONTH)), 2, '0'), '-', YEAR(DATE_SUB(NOW(), INTERVAL 2 MONTH))), '%d-%m-%Y')
AND g2.`buy_date` < STR_TO_DATE(CONCAT('01-', LPAD(MONTH(DATE_SUB(NOW(), INTERVAL 1 MONTH)), 2, '0'), '-', YEAR(DATE_SUB(NOW(), INTERVAL 1 MONTH))), '%d-%m-%Y')
JOIN `orders` g3
ON g3.`id_cust` = g1.`id_cust`
AND g3.`id_cust` = g2.`id_cust`
AND g3.`buy_date` >= STR_TO_DATE(CONCAT('01-', LPAD(MONTH(DATE_SUB(NOW(), INTERVAL 1 MONTH)), 2, '0'), '-', YEAR(DATE_SUB(NOW(), INTERVAL 1 MONTH))), '%d-%m-%Y')
AND g3.`buy_date` < STR_TO_DATE(CONCAT('01-', LPAD(MONTH(NOW()), 2, '0'), '-', YEAR(NOW())), '%d-%m-%Y')
WHERE g1.`buy_date` >= STR_TO_DATE(CONCAT('01-', LPAD(MONTH(DATE_SUB(NOW(), INTERVAL 3 MONTH)), 2, '0'), '-', YEAR(DATE_SUB(NOW(), INTERVAL 3 MONTH))), '%d-%m-%Y')
AND g1.`buy_date` < STR_TO_DATE(CONCAT('01-', LPAD(MONTH(DATE_SUB(NOW(), INTERVAL 2 MONTH)), 2, '0'), '-', YEAR(DATE_SUB(NOW(), INTERVAL 2 MONTH))), '%d-%m-%Y')
GROUP BY g1.`id_cust`
请帮助我简化我的语法,因为这是非常缓慢的时候,它是运行在大量的数据或如果我的语法错误,请纠正我的语法。
2条答案
按热度按时间ecfsfe2w1#
这个怎么样?
这只会过滤到你关心的三个月。然后它按年份和月份进行聚合,只返回第三行。
实际上,这更容易表达为:
mrfwxfqh2#
我会用戈登的第二个问题。但是如果您的代码正常工作(作为练习),您可以通过在上创建索引来优化执行时间
(buy_date, id_cust)
继续(id_cust, buy_date)
. 第一个用于where子句,第二个用于on子句。使用此架构
查询的结果是
没有使用键,“块嵌套循环”听起来很糟糕。
添加索引后
小提琴
现在看起来好多了,尽管它不再使用我的第一个索引(可能是由于groupby)。
然后我将查询简化为:
小提琴