寻求更简洁SQL查询:获取ColA对应的优先覆盖ColVal值
优化SQL查询:优先获取覆盖值,无则取默认值
表结构与测试数据
现有TestTable表的结构和测试数据如下:
CREATE TABLE [dbo].[TestTable]( [ColA] [varchar](10) NOT NULL, [ColB] [varchar](10) NOT NULL, [ColVal] [varchar](50) NULL, CONSTRAINT [pkTestTable] PRIMARY KEY CLUSTERED ( [ColA] ASC, [ColB] ASC ) ) INSERT INTO TestTable([ColA], [ColB], [ColVal]) VALUES ('A', N' ', N'A Description') INSERT INTO TestTable([ColA], [ColB], [ColVal]) VALUES ('A', N'override', N'Overridden Description for A') INSERT INTO TestTable([ColA], [ColB], [ColVal]) VALUES ('B', N' ', N'B Description')
需求说明
指定@colAParam参数值时:
- 若该
ColA对应的行中存在ColB非空格的记录(覆盖值),优先获取该行的ColVal - 若不存在这类记录,则获取
ColB为空格的默认行ColVal
首次尝试的问题查询
以下查询会返回多行,不符合预期:
DECLARE @colAParam varchar(10) = 'A' SELECT colval FROM TestTable WHERE ColB = coalesce(Nullif(ColB, N' '), ColB) AND colA = @colAParam -- 预期结果: 'Overridden Description for A' Set @colAParam = 'B' SELECT colval FROM TestTable WHERE ColB = coalesce(Nullif(ColB, N' '), ColB) AND colA = @colAParam -- 预期结果: 'B Description'
可用但不够简洁的IF EXISTS方案
用IF EXISTS可以实现需求,但需要两次查询表,语法不够简洁:
DECLARE @colAParam varchar(10) = 'A' if exists(select * from TestTable where nullif(ColB, N' ') is not null and colA = @colAParam) begin select colval from TestTable where nullif(ColB, N' ') is not null and colA = @colAParam end else begin select colVal from TestTable where nullif(ColB, N' ') is null and colA = @colAParam end
更简洁的优化方案
推荐两种只需要单次表扫描的简洁写法:
方法1:使用ROW_NUMBER()排序筛选
DECLARE @colAParam varchar(10) = 'A'; SELECT ColVal FROM ( SELECT ColVal, -- 给覆盖行(ColB非空格)分配最高优先级 ROW_NUMBER() OVER (PARTITION BY ColA ORDER BY CASE WHEN NULLIF(ColB, N' ') IS NOT NULL THEN 1 ELSE 2 END) AS rn FROM TestTable WHERE ColA = @colAParam ) t WHERE rn = 1;
方法2:使用TOP 1 + 优先级排序
写法更紧凑,适合单参数查询场景:
DECLARE @colAParam varchar(10) = 'B'; SELECT TOP 1 ColVal FROM TestTable WHERE ColA = @colAParam -- 让覆盖行排在最前面,取第一行即可 ORDER BY CASE WHEN NULLIF(ColB, N' ') IS NOT NULL THEN 1 ELSE 2 END;
这两种方法都只需要扫描一次表,效率比IF EXISTS的两次查询更高,语法也更简洁,能准确返回预期结果。
内容的提问来源于stack exchange,提问作者InquisitiveLad
相关产品推荐
相关产品推荐

