2013-06-28 123 views
0

假设我有一个表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

除非你使用动态SQL,NO。 –

+1

那么,你可以简化这些'SELECT DISTINCT A FROM SALES'等。你可以添加更多详细信息 – gbn

+2

不是没有切换到动态SQL,然后必须保护自己免受SQL注入。如果查询确实是相同的,并且具有相同的“含义”,这让我怀疑是否应该有5列 - 也许应该有一列表示某种形式的可以包含AE的“类型”,然后是包含“值”(当前包含在AE列中)的单列 - 换句话说,它看起来像您的模式设计意外地将实际的* data *放入了列*名称*中。 –

回答

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

你的点子打破存储过程合同,除非所有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;