SQL优化咨询:如何规避SELECT*与冗余ROW_NUMBER列问题?
解决SQL排序取顶的性能与冗余列问题
作为SQL新手,你的两个担忧非常合理,咱们一步一步来解决:
问题1:SELECT * 的性能隐患
SELECT * 会读取表中所有列,哪怕你只需要其中几列,这会额外消耗磁盘IO和内存资源,尤其是当PROF_BID表有大量非必要列时,性能损耗会很明显。而且如果后续表结构发生变化(比如新增列),SELECT * 还可能导致插入时列数不匹配,引发报错。
问题2:冗余的ROW_NUMBER列
你的核心需求是用ROW_NUMBER()做分组过滤,但不需要把这个行号插入到目标表中。原来的写法因为用了SELECT *,把子查询里的行号也带进来了,咱们可以通过只选择需要的业务列来避免这个问题。
优化后的SQL写法
INSERT INTO FNL_PROF_BID_ID_W2 (CUST_ORD_NBR, STR_LOC_ID, PROF_BID_ID) SELECT sub.CUST_ORD_NBR, sub.LOC_NBR AS STR_LOC_ID, sub.PROF_BID_ID FROM ( SELECT PB.CUST_ORD_NBR, PB.LOC_NBR, PB.PROF_BID_ID, -- 用别名rn存储行号,仅用于过滤 ROW_NUMBER() OVER( PARTITION BY PB.CUST_ORD_NBR, PB.LOC_NBR ORDER BY PB.PROF_BID_ID DESC, PB.CRT_TS DESC ) AS rn FROM PROF_BID PB ) sub WHERE sub.rn = 1
优化点说明
- 替换
SELECT*为明确列名:外层查询只选择目标表需要的CUST_ORD_NBR、LOC_NBR(映射为STR_LOC_ID)、PROF_BID_ID,避免读取冗余列,提升查询效率。 - 隔离行号列:子查询里给行号列起别名
rn,仅用于WHERE条件过滤,外层不选择该列,自然不会插入到目标表中,解决冗余问题。
更易读的CTE写法(可选)
如果觉得子查询嵌套有点绕,用CTE(公共表表达式)可以让逻辑更清晰:
WITH ranked_bids AS ( SELECT PB.CUST_ORD_NBR, PB.LOC_NBR, PB.PROF_BID_ID, ROW_NUMBER() OVER( PARTITION BY PB.CUST_ORD_NBR, PB.LOC_NBR ORDER BY PB.PROF_BID_ID DESC, PB.CRT_TS DESC ) AS rn FROM PROF_BID PB ) INSERT INTO FNL_PROF_BID_ID_W2 (CUST_ORD_NBR, STR_LOC_ID, PROF_BID_ID) SELECT CUST_ORD_NBR, LOC_NBR AS STR_LOC_ID, PROF_BID_ID FROM ranked_bids WHERE rn = 1
这两种写法都能满足你的需求,既解决了性能问题,又去掉了冗余的行号列,同时保证SQL逻辑正常运行。
内容的提问来源于stack exchange,提问作者Eric
相关产品推荐
相关产品推荐

