如何在SQL中根据OrderId和ItemId获取指定行的上下行?
获取目标记录上下行及检查同ItemId跨订单存在的SQL解决方案
没问题,我来帮你搞定这个需求!咱们的核心目标是:定位到OrderId=10且ItemId=2的目标记录后,找出所有ItemId=2的记录(按OrderDate排序)中该目标的上一行和下一行,同时验证ItemId=2是否存在于其他订单中。
核心思路
SQL的窗口函数LAG()和LEAD()是处理这类"前后行获取"需求的最优解——它们能在排序后的数据集里,直接提取当前行的前一行、后一行数据。我们的步骤是:先筛选所有ItemId=2的记录并按OrderDate(加Id做稳定排序)排序,标记目标行后,提取它的上下行信息,最后补充跨订单存在性检查。
完整可运行SQL代码
-- 定义表变量并插入测试数据 DECLARE @OderDetail table ( Id int primary key, OrderId int, ItemId int, OrderDate DateTime2, Lookup varchar(15) ) INSERT INTO @OderDetail VALUES (1, 10, 1, '2018-06-11', 'A'), (2, 10, 2, '2018-06-11', 'BE'), -- 目标行 (3, 2, 1, '2018-06-04', 'DR'), (4, 2, 2, '2018-06-04', 'D'), (5, 3, 2, '2018-06-14', 'DD'), (6, 4, 2, '2018-06-14', 'R'); -- 定义输入参数 DECLARE @ItemId int = 2, @OrderId int = 10; -- 分步处理的CTE WITH Item2Records AS ( -- 筛选所有ItemId=2的记录,计算前后行ID,标记目标行 SELECT *, -- LAG获取上一行ID,LEAD获取下一行ID,加Id确保OrderDate相同时排序稳定 LAG(Id) OVER (ORDER BY OrderDate, Id) AS PrevRowId, LEAD(Id) OVER (ORDER BY OrderDate, Id) AS NextRowId, CASE WHEN OrderId = @OrderId AND ItemId = @ItemId THEN 1 ELSE 0 END AS IsTargetRow FROM @OderDetail WHERE ItemId = @ItemId ), TargetRowInfo AS ( -- 提取目标行对应的前后行ID SELECT PrevRowId, NextRowId FROM Item2Records WHERE IsTargetRow = 1 ) -- 合并输出上下行数据+跨订单检查结果 SELECT '上一行' AS RowType, od.* FROM @OderDetail od JOIN TargetRowInfo tri ON od.Id = tri.PrevRowId UNION ALL SELECT '下一行' AS RowType, od.* FROM @OderDetail od JOIN TargetRowInfo tri ON od.Id = tri.NextRowId UNION ALL -- 输出ItemId=2是否存在于其他订单的检查结果 SELECT '跨订单检查' AS RowType, NULL AS Id, NULL AS OrderId, NULL AS ItemId, NULL AS OrderDate, CASE WHEN EXISTS (SELECT 1 FROM @OderDetail WHERE ItemId = @ItemId AND OrderId != @OrderId) THEN 'ItemId=2存在于其他订单中' ELSE 'ItemId=2仅存在于当前订单' END AS Lookup;
代码细节说明
- 稳定排序处理:窗口函数的
ORDER BY OrderDate, Id确保当多条记录OrderDate相同时,按Id排序,避免前后行结果不确定。 - CTE
Item2Records:集中处理筛选、前后行ID计算和目标行标记,逻辑清晰。 - 跨订单检查:用
EXISTS子句高效判断是否存在其他订单的ItemId=2记录,性能优于COUNT(*)。 - 边界情况兼容:如果目标行是排序后的第一行/最后一行,
LAG()/LEAD()会返回NULL,此时对应结果集不会有该行数据(因为JOIN匹配不到),符合预期。
运行结果
执行后你会得到:
- 目标行的上一行记录(
Id=4,OrderDate=2018-06-04) - 目标行的下一行记录(
Id=5,OrderDate=2018-06-14) - 跨订单检查结果:
ItemId=2存在于其他订单中
内容的提问来源于stack exchange,提问作者Lajith
相关产品推荐
相关产品推荐

