【问题标题】:Comma-separated list of dynamic column names逗号分隔的动态列名列表
【发布时间】:2014-06-04 19:52:27
【问题描述】:

我想在 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

【问题讨论】:

  • SQL Server 如何知道您需要 SUM 还是 AVG? AVG([Year]) 是什么意思?
  • 它必须是一个案例陈述。 AVG(year) 将取年份的平均值。这是一个虚拟代码,我真正的问题要复杂得多,我只是在考虑随机值的计算。
  • 那么上述样本数据的 AVG(Year) 应该是 2010 年?请不要为我们愚蠢。我们可以处理复杂的问题,最好解决问题的真实表现,而不是没有意义的虚构内容。
  • 是的,但不要太担心那个具体的例子。您可以根据需要将其更改为 SUM。
  • 所以更好地解释 - 用英语,而不是 python 或其他代码 - 你将如何决定是否对列应用 SUM() 或其他聚合(并指出是否有任何计算不是聚合)。你有一个你知道应该是 SUM() 的列名列表吗?这是基于数据类型,还是名称模式,还是列表中的顺序,还是...?

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


【解决方案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 是停止递归的常量

【讨论】:

    猜你喜欢
    • 2023-03-26
    • 1970-01-01
    • 1970-01-01
    • 2013-07-03
    • 2020-07-04
    • 1970-01-01
    • 2018-09-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多