【问题标题】:SQL Server How to mention dynamic column value should not be nullSQL Server如何提动态列值不应该为空
【发布时间】:2021-03-03 17:42:17
【问题描述】:

首先看几个屏幕截图。

查看第二个屏幕截图。其中 2010 FYA 和其余列是动态列。查看动态列值为 NULL 的第一条记录。现在告诉我如何在获取数据时提及动态列值不应为空。

这里是代码

   Set @AvgSql = @AvgSql+ 'Avg(CONVERT(decimal(20,6),['+@Period+'])) ['+@Period+'],'      

通过这种方式,我将动态列明智值存储到 #TmpZacksCons 临时表

 SET @sql='Insert Into #TmpZacksCons (Section, LineItem,Ord,      
 '+@PeriodCols+'      
 )      
 Select b.Section, b.LineItem,Max(Ord)+1 Ord,      
 '+@AvgSql+'      
  From #TmpAll_Broker_LI b       
  Group By b.Section, b.LineItem'      
 EXEC(@sql)  

这是我的最终查询,它返回我需要过滤掉空值的整个数据。不应出现空数据。

 SET @sql = '      
 Select XX.*,'''' scale,Isnull(AllowComma,''FALSE'') AllowComma,Isnull(AllowedDecimalPlace,''0'') AllowedDecimalPlace,      
     Isnull(AllowPercentageSign,''FALSE'') AllowPercentageSign,Isnull(CurrencySign,'''') CurrencySign,Isnull(BM_Denominator,'''') BM_Denominator      
 From       
 (      
 ---- Broker Detail      
 Select AA.Section,AA.LineItem,Csm.DisplayInCSM ,AA.BrokerCode Broker,AA.BrokerName,'''' BM_Element,'''' BM_Code,AA.Ord,AA.[Revise Date],AA.LineItemId,      
   Csm.ID,[FontName],[FontStyle],[FontSize],[UnderLine],[BGColor],[FGColor],[Indent],[Box],[HeadingSubHeading],      
 '+@PeriodCols+','+@PeriodColsComment +',LineItem_Comment,BrokerName_Comment,Date_Comment      
 From tblCSM_ModelDetails Csm LEFT OUTER JOIN  (      
Select b.*,L.ID LineItemId         
  From #TmpAll_Broker_LI b      
  INNER JOIN TblLineItemTemplate L ON TickerID='''+@TickerID+''' AND b.LineItem= L.LineItem      
     ) AA ON Csm.LineItemId=AA.LineItemId      
 WHERE Csm.CSM_ID='+TRIM(CONVERT(CHAR(10),@CSM_Id))+' AND Csm.BMID=0 AND Type !=''SHEET''      
 UNION       
 ----- Consensus      
 Select Section, b.LineItem,DisplayInCSM, '''' Broker,'''' BrokerName,'''' BM_Element,'''' BM_Code, Ord,'''' [Revise Date],L.ID LineItemID,      
   Csm.ID,[FontName],[FontStyle],[FontSize],[UnderLine],[BGColor],[FGColor],[Indent],[Box],[HeadingSubHeading],      
  '+@PeriodCols+','+@PeriodColsComment +',LineItem_Comment,BrokerName_Comment,Date_Comment      
  From #TmpZacksCons b      
  INNER JOIN TblLineItemTemplate L ON TickerID='''+@TickerID+''' AND b.LineItem= L.LineItem      
  INNER JOIN tblCSM_ModelDetails Csm ON Csm.LineItemID=L.ID      
  WHERE Csm.CSM_ID='+TRIM(CONVERT(CHAR(10),@CSM_Id))+' AND Csm.BMID=0      
 ---- Blue Metrics      
     UNION      
  Select Section, b.LineItem,DisplayInCSM,'''' Broker,'''' BrokerName,BM_Element,Code BM_Code, Ord,'''' [Revise Date],L.ID LineItemID,      
   Csm.ID,[FontName],[FontStyle],[FontSize],[UnderLine],[BGColor],[FGColor],[Indent],[Box],[HeadingSubHeading],      
   '+@PeriodCols+','+@PeriodColsComment +',LineItem_Comment,BrokerName_Comment,Date_Comment      
  From #TmpBM b      
  INNER JOIN TblLineItemTemplate L ON TickerID='''+@TickerID+''' AND b.LineItem= L.LineItem      
  INNER JOIN tblCSM_ModelDetails Csm ON Csm.BMID=b.code AND Csm.LineItemID=L.ID      
  WHERE Csm.CSM_ID='+TRIM(CONVERT(CHAR(10),@CSM_Id))+'      
  AND Ord IS NOT NULL      
 ) XX       
 Left Outer Join tblLiConfig ZZ      
  On XX.Section=ZZ.Section And XX.LineItem=ZZ.LI And ZZ.Ticker='''+@Ticker+'''      
 Order by ID,Ord,BM_Code,LineItem,BrokerName'  

【问题讨论】:

  • 您的问题到底是什么?不要忘记,我们无法运行您的代码,当然您不应该期待我们在该图像中转录所有数据。花点时间给我们一个minimal reproducible example(我怀疑我们需要所有这些数据)。另外,不要将参数注入动态语句parametrise your queries
  • 推荐阅读:SQL Injection.

标签: sql sql-server tsql dynamic-sql


【解决方案1】:

好的...对不起,这是一个错误的答案。 真的不好的答案。当您现在需要修复并且没有时间正确解决问题时,这是一种答案。

真正的解决方法是在将没有有效值的行合并到用于创建表的数据集之前排除它们。但是,如果不更深入地了解您的流程/数据,我无法做到这一点。相反,我有一个完整的 hackjob。

无论如何,据我所知

  • 在表中#TmpZacksCons
  • 您有一些行,其中与日期相关的所有列都为 NULL
  • 您想排除那些
  • 列名是动态设置的 - 它们在变量 @PeriodCols 中

您可以做的是从#TmpZacksCons 中删除所有为NULL 的行。当然,问题在于这些列是动态创建的。

所以,在你现有的命令之后

 SET @sql='Insert Into #TmpZacksCons (Section, LineItem,Ord,      
 '+@PeriodCols+'      
 )      
 Select b.Section, b.LineItem,Max(Ord)+1 Ord,      
 '+@AvgSql+'      
  From #TmpAll_Broker_LI b       
  Group By b.Section, b.LineItem'      
 EXEC(@sql) 

我建议使用 DELETE 命令来删除所有列都为 NULL 的命令。

更新

(这个基于更新知识的新版本 - 我不认为 COALESCE 可以返回 NULL)

这里的hackjob是基于我们不知道列名的事实,所以我们不能只测试第1列是否为空,第2列是否为空等。 所以我正在做的是使用 COALESCE 表达式来查找是否所有列都是 NULL,因为它将返回列表中的第一个非 NULL 值。

SET @sql='DELETE FROM #TmpZacksCons 
          WHERE COALESCE('+@PeriodCols+',NULL) IS NULL'
EXEC (@sql)

如果 COALESCE 表达式返回 NULL,则表示所有列都有 NULL 值。

请注意 COALESCE 中的额外 NULL 存在,以防列列表只有 1 列。

以前的版本 - 不再相关

所以我正在做的是通过COALESCE 表达式创建一个“幻数”,它表示所有列都是 NULL,该表达式在列表中找到第一个非 NULL 值。

所以,在你上面的命令之后,我建议

SET @sql='DELETE FROM #TmpZacksCons 
          WHERE COALESCE('+@PeriodCols+',-99999.9999) = -99999.9999'
EXEC (@sql)

如果所有值都为 NULL,COALESCE 将返回 -99999.9999,然后触发删除。

当然,上面的问题是,如果任何 实际 值等于该幻数 -99999.9999,它可能会删除该行。

【讨论】:

  • COALESCE 将在列为空时返回 -99999.9999?假设列不为空,而列的值为空……那我该如何管理?谢谢你的回答。
  • 对不起,我应用了你的代码,但没有用。这是您看到完整 SP 代码的 url,并告诉我如何过滤空值。 github.com/karlosRivera/SampleRepo/blob/master/Dynamic%20SP.txt
  • 很抱歉 - 我无法理解您的代码,我可能需要几个小时(即使有完整的数据等)才能弄清楚它在做什么。如果它不能满足您的需要,您可能希望将其删除为“已接受的答案”。但是,我认为如果这不起作用,您将需要澄清实际需要什么。 Re COALESCE - 它的工作方式是在列表中找到第一个 NOT NULL 值。鉴于您有动态列,很难对检查进行显式编码 - 我使用的是 COALESCE 可以采用逗号分隔的列列表这一事实。但是,它不适用于空白。
  • 请注意,我将此答案更新为 COALESCE 表达式中更强大的答案/方法。它可能会修复由于计算无法正常工作而发生的错误(例如,如果它没有返回相同的数据类型)。但是,它不会解决“空白呢?”问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-15
  • 1970-01-01
相关资源
最近更新 更多