SQL Server:多SELECT语句下获取行号异常问题咨询
解决多SELECT合并获取行号的问题
嘿,我能理解你遇到的困扰——单独查每个ItemId下的评论行号都没问题,一合并就出错对吧?大概率是合并的写法没处理好,导致原本各自独立的行号计算逻辑被破坏了。
先说说你可能踩的坑
如果你是直接用UNION把两个查询硬拼起来,看起来像是这样:
-- 错误示例:这样写可能因UNION触发额外排序,导致行号不符合预期 SELECT num FROM (...) WHERE CommentId=100 UNION SELECT num FROM (...) WHERE CommentId=200
其实这种写法本身不一定错,但如果你的需求是分别保留每个ItemId分组下的行号,那更推荐用UNION ALL(避免不必要的去重和排序开销)。不过更关键的是,这种写法重复了代码,不够高效,我们可以用更优雅的方式实现。
推荐的优化写法
不需要写两个独立的子查询,我们可以用PARTITION BY ItemId让行号按照每个ItemId单独计算,然后再筛选目标的CommentId组合:
SELECT num FROM ( SELECT ItemId, CommentId, -- 按ItemId分组,每组内按CreatedDate倒序生成行号 ROW_NUMBER() OVER (PARTITION BY ItemId ORDER BY CreatedDate DESC) AS num FROM ItemComments -- 先过滤出需要的ItemId,减少计算量 WHERE ItemId IN (10, 20) ) AS numbered -- 筛选目标的ItemId和CommentId组合 WHERE (ItemId = 10 AND CommentId = 100) OR (ItemId = 20 AND CommentId = 200);
这个写法的好处是只扫描一次表,比两个独立查询更高效,而且行号的计算逻辑是完全按照每个ItemId分组独立进行的,和你单独执行每个查询的结果完全一致。
如果你坚持要合并两个独立查询
那记得用UNION ALL代替UNION(除非你确实需要去重),这样能保证两个查询的结果互不干扰,行号还是各自分组计算的:
-- 正确的合并写法 SELECT num FROM ( SELECT ItemId, CommentId, ROW_NUMBER() OVER (ORDER BY CreatedDate DESC) AS num FROM ItemComments WHERE ItemId = 10 ) AS numbered WHERE numbered.CommentId = 100 UNION ALL SELECT num FROM ( SELECT ItemId, CommentId, ROW_NUMBER() OVER(ORDER BY CreatedDate DESC) AS num FROM ItemComments WHERE ItemId = 20 ) AS numbered WHERE numbered.CommentId = 200;
简单来说,核心就是保证ROW_NUMBER()是在每个ItemId的分组内单独计算,而不是在合并后的结果集里计算,这样就能得到和单独查询一致的行号啦。
内容的提问来源于stack exchange,提问作者Tom
相关产品推荐
相关产品推荐

