TSQL查询难题:如何编写WHERE条件筛选特定状态行号+1的记录
如何筛选行号等于特定状态对应行号+1的TSQL记录
看起来你已经把基础的分组、行号计算逻辑搭好了,核心问题是怎么正确引用特定状态对应的行号来筛选目标记录。你之前尝试的case when写法之所以无效,是因为它试图用当前行的rn来计算,逻辑上根本不成立——总不能让一个数等于它自己加1吧😅。
下面给你两种可行的解决方案,都是基于先获取目标状态(比如sold)对应的rn值,再用这个值+1作为筛选条件:
方法一:用CTE简化查询 + 子查询获取目标rn
先把原来的嵌套查询改成CTE,让逻辑更清晰,然后直接在WHERE里通过子查询拿到sold状态的rn再加1:
WITH log_cte AS ( SELECT id, status, MAX(log_date) AS max_log_date, ROW_NUMBER() OVER (PARTITION BY id ORDER BY MAX(log_date)) AS rn FROM LOG_table WHERE id = 1234 GROUP BY id, status ) SELECT id, status, max_log_date, rn FROM log_cte WHERE rn = (SELECT rn + 1 FROM log_cte WHERE status = 'sold')
这个写法的好处是简洁,适合单个id的场景,因为你的查询里已经限定了id=1234,所以子查询只会返回一个rn值。
方法二:用JOIN关联目标状态记录(更灵活)
如果之后需要扩展到多个id的情况,或者想让逻辑更直观,可以用JOIN的方式,把目标状态的记录和要筛选的记录关联起来:
WITH log_cte AS ( SELECT id, status, MAX(log_date) AS max_log_date, ROW_NUMBER() OVER (PARTITION BY id ORDER BY MAX(log_date)) AS rn FROM LOG_table WHERE id = 1234 GROUP BY id, status ) SELECT l.id, l.status, l.max_log_date, l.rn FROM log_cte l JOIN log_cte target ON l.id = target.id AND l.rn = target.rn + 1 WHERE target.status = 'sold'
这种写法把“找目标状态的rn”和“筛选rn=目标rn+1的记录”拆成了关联逻辑,可读性更强,也更容易扩展。
补充说明
你的分组逻辑是GROUP BY id, status,所以同一个id下每个status只会有一条记录,这保证了子查询或者JOIN时不会返回多条结果,避免出现rn匹配多个值的问题。如果之后分组逻辑有变化,记得考虑是否需要用TOP 1或者聚合函数来确保只拿到一个目标rn值。
内容的提问来源于stack exchange,提问作者Ziil
相关产品推荐
相关产品推荐

