以逗号分隔的动态列名列表

时间:2014-06-04 19:52:27

标签: sql sql-server stored-procedures sql-server-2012

我想在SQL Server 2012中使用逗号分隔的输入参数创建存储过程,该参数将定义选择哪些列。我需要对一些列执行简单的计算,例如SUM或AVG。

表中的示例数据:

Amount Cost   Year Author
15.00  11.00  2011 Lloyd Christmas
17.00  50.00  2009 Billy Madison
12.00  10.00  2010 Joe Dirt

我会使用与此类似的语法执行SP(如果它使代码更容易,则可以是动态的):

exec StoredProc @CSV = 'Amount,Year'

使这很困难的是我需要对所选列进行简单的计算。

Select SUM([Amount]), AVG([YEAR]) 
FROM TBL

另一个例子:

exec StoredProc @CSV = "Amount,Cost,Year"

Select SUM([Amount]),SUM(Cost),AVG([YEAR]) 
FROM TBL

1 个答案:

答案 0 :(得分:1)

要获得在行中拆分的参数中的单词,您可以使用递归CTE

Declare @CSV NVarchar(255) = 'Amount,Cost,Year'

;WITH Splitter AS (
  SELECT @CSV String
       , WordCounter = 0
       , NWordStart = 1
       , NWordEnd = CHARINDEX(',', @CSV)
       , Word = CAST('' AS NVarchar(255))
       , WordNumber = LEN(@CSV) - LEN(REPLACE(@CSV, ',', '')) + 1
  UNION ALL
  SELECT s.String
       , WordCounter = s.WordCounter + 1
       , NWordStart = s.NWordEnd + 1
       , NWordEnd = COALESCE(NULLIF(CHARINDEX(',', s.String, NWordEnd + 1), 0)
                           , LEN(s.String) + 1)
       , Word = Cast(SUBSTRING(String, s.NWordStart, s.NWordEnd - s.NWordStart) 
                  AS NVarchar(255))
       , WordNumber = s.WordNumber
  FROM   Splitter s
  WHERE  s.WordCounter + 1 <= s.WordNumber
)
SELECT Word
FROM   Splitter
WHERE  WordCounter > 0

SQLFiddle demo

将结果放在临时表或表变量中,然后使用它们来创建动态查询。

主查询中的WHERE条件会删除第一个结果,因为为简化SUBSTRING,值会混合:

  • NWordStartNWordEnd是下一个单词的开头和结尾的位置
  • WordCounterWord其他字段是最新的,因此第0个字为空
  • WordNumber是一个停止递归的常量