【问题标题】:SQL Server: how does quoting work in creating columns inside for-loop dynamically?SQL Server:引用如何在 for 循环中动态创建列?
【发布时间】:2023-12-20 10:16:01
【问题描述】:

我认为我遇到了引用问题。我要换

  ,CAST(REPLACE([NET_VALUE_1M],',','.') as float)/SUM(CAST(REPLACE([NET_VALUE_1M],',','.') as float)) OVER (PARTITION BY [ID] ORDER BY [CMONTH] ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) as 'NET_VALUE_1M_PROP_2Mp'
  ,CAST(REPLACE([NET_VALUE_1M],',','.') as float)/SUM(CAST(REPLACE([NET_VALUE_1M],',','.') as float)) OVER (PARTITION BY [ID] ORDER BY [CMONTH] ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) as 'NET_VALUE_1M_PROP_3Mp'
  ,CAST(REPLACE([NET_VALUE_1M],',','.') as float)/SUM(CAST(REPLACE([NET_VALUE_1M],',','.') as float)) OVER (PARTITION BY [ID] ORDER BY [CMONTH] ROWS BETWEEN 3 PRECEDING AND CURRENT ROW) as 'NET_VALUE_1M_PROP_4Mp'
  ,CAST(REPLACE([NET_VALUE_1M],',','.') as float)/SUM(CAST(REPLACE([NET_VALUE_1M],',','.') as float)) OVER (PARTITION BY [ID] ORDER BY [CMONTH] ROWS BETWEEN 4 PRECEDING AND CURRENT ROW) as 'NET_VALUE_1M_PROP_5Mp'
  ,CAST(REPLACE([NET_VALUE_1M],',','.') as float)/SUM(CAST(REPLACE([NET_VALUE_1M],',','.') as float)) OVER (PARTITION BY [ID] ORDER BY [CMONTH] ROWS BETWEEN 5 PRECEDING AND CURRENT ROW) as 'NET_VALUE_1M_PROP_6Mp'
  ,CAST(REPLACE([NET_VALUE_1M],',','.') as float)/SUM(CAST(REPLACE([NET_VALUE_1M],',','.') as float)) OVER (PARTITION BY [ID] ORDER BY [CMONTH] ROWS BETWEEN 6 PRECEDING AND CURRENT ROW) as 'NET_VALUE_1M_PROP_7Mp'
  ,CAST(REPLACE([NET_VALUE_1M],',','.') as float)/SUM(CAST(REPLACE([NET_VALUE_1M],',','.') as float)) OVER (PARTITION BY [ID] ORDER BY [CMONTH] ROWS BETWEEN 7 PRECEDING AND CURRENT ROW) as 'NET_VALUE_1M_PROP_8Mp'
  ,CAST(REPLACE([NET_VALUE_1M],',','.') as float)/SUM(CAST(REPLACE([NET_VALUE_1M],',','.') as float)) OVER (PARTITION BY [ID] ORDER BY [CMONTH] ROWS BETWEEN 8 PRECEDING AND CURRENT ROW) as 'NET_VALUE_1M_PROP_9Mp'
  ,CAST(REPLACE([NET_VALUE_1M],',','.') as float)/SUM(CAST(REPLACE([NET_VALUE_1M],',','.') as float)) OVER (PARTITION BY [ID] ORDER BY [CMONTH] ROWS BETWEEN 9 PRECEDING AND CURRENT ROW) as 'NET_VALUE_1M_PROP_10Mp'
  ,CAST(REPLACE([NET_VALUE_1M],',','.') as float)/SUM(CAST(REPLACE([NET_VALUE_1M],',','.') as float)) OVER (PARTITION BY [ID] ORDER BY [CMONTH] ROWS BETWEEN 10 PRECEDING AND CURRENT ROW) as 'NET_VALUE_1M_PROP_11Mp'
  ,CAST(REPLACE([NET_VALUE_1M],',','.') as float)/SUM(CAST(REPLACE([NET_VALUE_1M],',','.') as float)) OVER (PARTITION BY [ID] ORDER BY [CMONTH] ROWS BETWEEN 11 PRECEDING AND CURRENT ROW) as 'NET_VALUE_1M_PROP_12Mp'
  ,CAST(REPLACE([NET_VALUE_1M],',','.') as float)/SUM(CAST(REPLACE([NET_VALUE_1M],',','.') as float)) OVER (PARTITION BY [ID] ORDER BY [CMONTH] ROWS BETWEEN 12 PRECEDING AND CURRENT ROW) as 'NET_VALUE_1M_PROP_13Mp'

有一个while循环

SELECT

      CAST(REPLACE([NET_VALUE_1M],',','.') as float)
      /
     SUM(CAST(REPLACE([NET_VALUE_1M],',','.') as float)) 
         OVER (PARTITION BY [ID] ORDER BY [CMONTH] 
            ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) as 'NET_VALUE_1M_PROP_2Mp'


      DECLARE @cnt INT =2;
      DECLARE @cnt_total INT =12;

      WHILE @cnt < @cnt_total 
      BEGIN
        DECLARE @SQL NVARCHAR(MAX);
        SET @SQL =',CAST(REPLACE([NET_VALUE_1M],',','.') as float)
             /
          SUM(CAST(REPLACE([NET_VALUE_1M],',','.') as float)) 
                 OVER (PARTITION BY [ID] ORDER BY [CMONTH] ROWS 
                   BETWEEN @cnt PRECEDING AND CURRENT ROW) 
                       as ['NET_VALUE_1M_PROP_']+@cnt+['Mp']'
      EXECUTE(@SQL)

        SET @cnt=@cnt+1;
      END;


  FROM [Channel_AGG]

导致错误:

消息 102,第 15 级,状态 1,第 13 行
',' 附近的语法不正确。

消息 156,第 15 级,状态 1,第 20 行
关键字“FROM”附近的语法不正确。

引用如何声明 SQL 命令?我尝试了[' 开场报价和'] 结束报价,如此处所示How to create/add columns using a variable in a loop,但错误仍在继续。那么在 SQL Server 2014 的 for 循环中创建初始命令?

【问题讨论】:

  • 你先声明@SQL怎么样?
  • @Jeremy 正确,DELARE @SQL NVARCHAR(MAX),但引用问题仍然存在。
  • 好吧,它不包含在您的代码中……我们是通灵者吗? :)
  • 抱歉,dynamic SQL 不能这样工作。您必须在字符串 var 中构建整个 SQL 语句,然后执行它。您能解释一下为什么要放弃第一种方法吗?输出列的数量是否不断变化?

标签: sql-server for-loop sql-server-2014 quotes declare


【解决方案1】:

我不确定您要做什么,或者您在尝试执行不完整的代码片段时期望发生什么,但是您的引用问题可以通过对字符串中的每个单引号使用两个单引号来解决.例如:

 ',CAST(REPLACE([NET_VALUE_1M],'','',''.'') as float)
             /
          SUM(CAST(REPLACE([NET_VALUE_1M],'','',''.'') as float)) 
                 OVER (PARTITION BY [ID] ORDER BY [CMONTH] ROWS 
                   BETWEEN '+convert(nvarchar(10),@cnt-1)+' PRECEDING AND CURRENT ROW) 
                       as [NET_VALUE_1M_PROP_'+convert(nvarchar(10),@cnt)+'Mp]'

您还需要在连接之前将@cnt 转换为字符类型。

你应该在你的循环之外声明你的@sql,并且可能是连接的(例如@sql =+ ...@sql = @sql + ...)而不是重置循环内的值。

与其盲目尝试exec(@sql),不如看看你正在使用print @sqlselect @sql 创建什么。

【讨论】: