假设我有一个名为Sales
的表。
我还有一个类似的存储过程:
SELECT A FROM SALES GROUP BY A
SELECT B FROM SALES GROUP BY B
SELECT C FROM SALES GROUP BY C
SELECT D FROM SALES GROUP BY D
SELECT E FROM SALES GROUP BY E
我可以将该存储过程中SELECT
个语句的数量减少到只有一个吗?
换句话说,是否可以将group by中的列名用作参数?
答案 0 :(得分:2)
选项A - 您可以使用动态sql:
DECLARE @sql NVARCHAR(MAX)
SELECT 'SELECT ' + @col + ' FROM SALES GROUP BY ' + col + '; '
EXEC (@sql)
选项B - 您可以使用CASE
SELECT CASE @col WHEN 'A' THEN A
WHEN 'B' THEN B
WHEN 'C' THEN C
WHEN 'D' THEN D
WHEN 'E' THEN E
END
FROM SALES
GROUP BY CASE @col WHEN 'A' THEN A
WHEN 'B' THEN B
WHEN 'C' THEN C
WHEN 'D' THEN D
WHEN 'E' THEN E
END
(两个选项都接收@col作为字符串参数)
答案 1 :(得分:1)
您的想法会破坏存储过程合同,除非所有5列都是兼容的数据类型,因为返回类型每次都会更改。这意味着更复杂的客户端代码来处理此返回类型更改
如果它们都是相同的数据类型,为避免动态SQL,您可以使用此
SELECT DISTINCT
CASE @param
WHEN @param = 'A' THEN A
WHEN @param = 'B' THEN B
WHEN @param = 'C' THEN C
WHEN @param = 'D' THEN D
WHEN @param = 'E' THEN E
END
FROM
SALES;
但它仍然效率不高。
如果您需要不同的聚合(如SUM或COUNT),则可以使用其他方法在没有数据类型兼容性或动态SQL的情况下执行此操作。那么,您想要解决的实际问题是什么?
例如,这意味着您可以在客户端中干净地选择A到E
SELECT DISTINCT
COUNT(*) OVER (GROUP BY A) AS cntA,
COUNT(*) OVER (GROUP BY B) AS cntB,
COUNT(*) OVER (GROUP BY C) AS cntC,
COUNT(*) OVER (GROUP BY D) AS cntD,
COUNT(*) OVER (GROUP BY E) AS cntE
FROM
SALES;