按列名称分组作为参数

时间:2013-06-28 07:01:09

标签: sql tsql sql-server-2005 stored-procedures group-by

假设我有一个名为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中的列名用作参数?

2 个答案:

答案 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;