You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 04:23:32