Vue多选组件联动SQL查询:实现最多4项的动态统计需求
解决方案:动态生成适配1-4个项目的统计SQL
要适配用户选择1-4个项目的动态场景,不能写死固定数量的case when,得用动态SQL根据选择的项目数自动生成统计列。下面是两种可行的实现方式:
方法一:基于STRING_SPLIT(SQL Server 2016+)
利用SQL Server自带的字符串拆分函数,先把输入的项目列表拆成行数据,再动态拼接统计列:
DECLARE @item NVARCHAR(MAX) = 'App1,App2,App3'; -- 可替换为用户选择的1-4个项目 DECLARE @sql NVARCHAR(MAX); DECLARE @columns NVARCHAR(MAX); -- 1. 生成动态列:每个项目对应一个count统计列,别名按app1、app2...命名 WITH SplitApps AS ( SELECT value AS AppName, ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS RowNum FROM STRING_SPLIT(@item, ',') ) SELECT @columns = STRING_AGG( 'COUNT(CASE WHEN app = ''' + AppName + ''' THEN 1 END) AS app' + CAST(RowNum AS VARCHAR), ', ' ) FROM SplitApps; -- 2. 拼接完整SQL并执行 SET @sql = N' SELECT [user], ' + @columns + ' FROM AppTable WHERE app IN (''' + REPLACE(@item, ',', ''', ''') + ''') -- 过滤数据,提升性能 GROUP BY [user] ORDER BY COUNT(*) DESC'; EXEC sp_executesql @sql;
关键点说明:
STRING_SPLIT把逗号分隔的项目拆成每行一个App,用ROW_NUMBER()生成序号来命名列(app1、app2...)STRING_AGG把每个项目对应的统计列拼接成字符串,避免手动写死数量- 加了
WHERE app IN (...)过滤数据,只统计选中的项目,减少计算量
方法二:兼容旧版SQL Server(无STRING_SPLIT)
如果你的SQL Server版本低于2016,可以用自定义字符串拆分函数来替代:
先创建自定义拆分函数:
CREATE FUNCTION dbo.SplitString(@str NVARCHAR(MAX), @delimiter CHAR(1)) RETURNS @result TABLE (AppName NVARCHAR(100), RowNum INT) AS BEGIN DECLARE @pos INT, @start INT = 1, @rowNum INT = 1; WHILE CHARINDEX(@delimiter, @str, @start) > 0 BEGIN SET @pos = CHARINDEX(@delimiter, @str, @start); INSERT INTO @result VALUES(SUBSTRING(@str, @start, @pos - @start), @rowNum); SET @start = @pos + 1; SET @rowNum = @rowNum + 1; END INSERT INTO @result VALUES(SUBSTRING(@str, @start, LEN(@str) - @start + 1), @rowNum); RETURN; END
然后用动态SQL生成统计:
DECLARE @item NVARCHAR(MAX) = 'App1,App2'; DECLARE @sql NVARCHAR(MAX); DECLARE @columns NVARCHAR(MAX); -- 生成动态列 SELECT @columns = COALESCE(@columns + ', ', '') + 'COUNT(CASE WHEN app = ''' + AppName + ''' THEN 1 END) AS app' + CAST(RowNum AS VARCHAR) FROM dbo.SplitString(@item, ','); -- 拼接并执行SQL SET @sql = N' SELECT [user], ' + @columns + ' FROM AppTable WHERE app IN (''' + REPLACE(@item, ',', ''', ''') + ''') GROUP BY [user] ORDER BY COUNT(*) DESC'; EXEC sp_executesql @sql;
注意事项:
- 如果项目名称包含特殊字符(比如单引号),要先用
REPLACE(AppName, '''', '''''')转义,避免SQL注入 - 用
sp_executesql执行动态SQL比直接EXEC更安全,也支持参数化(如果需要的话,可以把@item作为参数传入)
内容的提问来源于stack exchange,提问作者WBayoomi
相关产品推荐
相关产品推荐

