如何查询连续两次订购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把两条连续订单都查出来。
这两种方法都会输出你要的预期结果:
| Customerid | Createdate | Orderid | RestaurantName |
|---|---|---|---|
| 45 | 2019-08-03 | 1338 | KFC |
| 45 | 2019-08-04 | 3266 | KFC |
内容的提问来源于stack exchange,提问作者Mg Mogaki




