You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何查询连续两次订购KFC的客户及对应订单详情?

解决连续两次KFC订单的筛选问题

我来帮你搞定这个需求——你的原SQL没得到预期结果,核心问题是依赖了Order_rank表的Rank字段,但这个字段看起来并不是按客户订单时间排序的连续序号,完全没法用来判断“连续两次订购KFC”这个条件。

下面给出两种靠谱的实现方案,适配不同的数据库环境:


方法1:用窗口函数(推荐,适合现代数据库)

利用LAG()LEAD()窗口函数,轻松获取每个客户的上一个/下一个订单的餐厅信息,直接判断是否连续为KFC:

WITH customer_order_sequence AS (
    SELECT 
        Customerid,
        Createdate,
        Orderid,
        Restaurantname,
        -- 获取当前订单的下一个订单的餐厅名(按时间排序)
        LEAD(Restaurantname) OVER (PARTITION BY Customerid ORDER BY Createdate) AS next_restaurant,
        -- 获取当前订单的上一个订单的餐厅名
        LAG(Restaurantname) OVER (PARTITION BY Customerid ORDER BY Createdate) AS prev_restaurant
    FROM Orders
    WHERE OrderStatus = 'Accepted' -- 只统计已确认的有效订单
)
SELECT 
    Customerid,
    Createdate,
    Orderid,
    Restaurantname
FROM customer_order_sequence
WHERE 
    -- 要么当前是KFC且下一个也是KFC
    (Restaurantname = 'KFC' AND next_restaurant = 'KFC')
    -- 要么当前是KFC且上一个也是KFC(避免漏掉连续订单的第二条)
    OR (Restaurantname = 'KFC' AND prev_restaurant = 'KFC')
ORDER BY Customerid, Createdate;

方法2:自连接表(兼容老版本数据库)

如果你的数据库不支持窗口函数(比如MySQL 5.x),可以用自连接的方式匹配连续订单:

-- 先取连续KFC订单的第一条
SELECT 
    o1.Customerid,
    o1.Createdate,
    o1.Orderid,
    o1.Restaurantname
FROM Orders o1
JOIN Orders o2 
    ON o1.Customerid = o2.Customerid
    AND o1.Createdate < o2.Createdate
    -- 确保两个订单之间没有其他订单(真正连续)
    AND NOT EXISTS (
        SELECT 1 FROM Orders o3
        WHERE o3.Customerid = o1.Customerid
        AND o3.Createdate > o1.Createdate
        AND o3.Createdate < o2.Createdate
    )
WHERE 
    o1.Restaurantname = 'KFC'
    AND o2.Restaurantname = 'KFC'
    AND o1.OrderStatus = 'Accepted'
    AND o2.OrderStatus = 'Accepted'

UNION

-- 再取连续KFC订单的第二条
SELECT 
    o2.Customerid,
    o2.Createdate,
    o2.Orderid,
    o2.Restaurantname
FROM Orders o1
JOIN Orders o2 
    ON o1.Customerid = o2.Customerid
    AND o1.Createdate < o2.Createdate
    AND NOT EXISTS (
        SELECT 1 FROM Orders o3
        WHERE o3.Customerid = o1.Customerid
        AND o3.Createdate > o1.Createdate
        AND o3.Createdate < o2.Createdate
    )
WHERE 
    o1.Restaurantname = 'KFC'
    AND o2.Restaurantname = 'KFC'
    AND o1.OrderStatus = 'Accepted'
    AND o2.OrderStatus = 'Accepted'

ORDER BY Customerid, Createdate;

为什么这两种方法能行?

  • 窗口函数法:通过PARTITION BY Customerid把每个客户的订单单独分组,ORDER BY Createdate按时间排序后,LEAD()/LAG()就能拿到相邻订单的信息,直接判断是否连续为KFC,代码简洁效率高。
  • 自连接法:通过匹配同一个客户的两个订单,再用NOT EXISTS确保中间没有其他订单,保证是真正的连续,最后用UNION把两条连续订单都查出来。

这两种方法都会输出你要的预期结果:

CustomeridCreatedateOrderidRestaurantName
452019-08-031338KFC
452019-08-043266KFC

内容的提问来源于stack exchange,提问作者Mg Mogaki

火山引擎 最新活动