MySQL如何查询客户上月是否存在对应订单记录?
判断每条记录的custId是否存在上月订单的SQL查询方案
嘿,这个需求我之前做客户复购分析的时候刚好碰到过!核心思路就是针对表中每一条订单记录,检查同一个客户在上个月有没有留下过订单痕迹。下面我分几种常用数据库给你分享实用的写法,都是实际项目里跑通的:
方法1:用EXISTS子查询(推荐,性能更优)
EXISTS的优势在于只要找到匹配的记录就会停止检索,比COUNT或者全连接效率高很多,尤其数据量大的时候。
MySQL 版本
假设你的表名叫orders,直接用DATE_SUB处理日期,匹配上月的年月:
SELECT o.custId, o.orderDate, CASE WHEN EXISTS ( SELECT 1 FROM orders o2 WHERE o2.custId = o.custId AND YEAR(o2.orderDate) = YEAR(DATE_SUB(o.orderDate, INTERVAL 1 MONTH)) AND MONTH(o2.orderDate) = MONTH(DATE_SUB(o.orderDate, INTERVAL 1 MONTH)) ) THEN '是' ELSE '否' END AS has_last_month_order FROM orders o;
PostgreSQL 版本
PostgreSQL用date_trunc可以更简洁地截取月份,或者用EXTRACT取年月都可以:
SELECT o.custId, o.orderDate, CASE WHEN EXISTS ( SELECT 1 FROM orders o2 WHERE o2.custId = o.custId AND date_trunc('month', o2.orderDate) = date_trunc('month', o.orderDate - INTERVAL '1 month') ) THEN 'Yes' ELSE 'No' END AS has_last_month_order FROM orders o;
SQL Server 版本
用DATEADD来往前推一个月,配合DATEPART取年月做匹配:
SELECT o.custId, o.orderDate, CASE WHEN EXISTS ( SELECT 1 FROM orders o2 WHERE o2.custId = o.custId AND DATEPART(YEAR, o2.orderDate) = DATEPART(YEAR, DATEADD(MONTH, -1, o.orderDate)) AND DATEPART(MONTH, o2.orderDate) = DATEPART(MONTH, DATEADD(MONTH, -1, o.orderDate)) ) THEN '是' ELSE '否' END AS has_last_month_order FROM orders o;
方法2:自连接 + GROUP BY(适合需要额外统计的场景)
如果你不仅要判断存在性,还想知道上月有多少订单,可以用这种方式。单纯判断的话还是EXISTS更高效:
-- 以MySQL为例,其他数据库替换日期函数即可 SELECT o.custId, o.orderDate, CASE WHEN COUNT(o2.custId) > 0 THEN '是' ELSE '否' END AS has_last_month_order, COUNT(o2.custId) AS last_month_order_count -- 额外统计上月订单数 FROM orders o LEFT JOIN orders o2 ON o2.custId = o.custId AND YEAR(o2.orderDate) = YEAR(DATE_SUB(o.orderDate, INTERVAL 1 MONTH)) AND MONTH(o2.orderDate) = MONTH(DATE_SUB(o.orderDate, INTERVAL 1 MONTH)) GROUP BY o.custId, o.orderDate;
一些实用提示
- 日期类型兼容:如果
orderDate是带时间的datetime类型,不用额外处理,因为我们只匹配年月,日和时间会被忽略。 - 性能优化:给
custId和orderDate建个联合索引(比如CREATE INDEX idx_cust_orderdate ON orders(custId, orderDate);),能让查询速度飞起来,大数据量下效果特别明显。 - 跨年处理:比如当前订单是1月份的,SQL会自动匹配去年12月的订单,不用额外写逻辑处理跨年情况。
内容的提问来源于stack exchange,提问作者CraigV
相关产品推荐
相关产品推荐

