繁体   English   中英

动态SQL:SSRS数据集查询的HAVING子句中的CASE表达式

[英]Dynamic SQL: CASE expression in HAVING clause for SSRS dataset query

我的一张表包含6位标志:

tblDocumentFact.useCase1
tblDocumentFact.useCase2
tblDocumentFact.useCase3
tblDocumentFact.useCase4
tblDocumentFact.useCase5
tblDocumentFact.useCase6 

位标志用于通过HAVING子句限制返回的数据,例如:

HAVING tblDocumentFact.useCase4 = 1     /* '1' means 'True' */

在静态查询中有效。 该查询用于SQL Server Reporting Services报表的数据集。 我希望有1个带有@UserChoice输入参数的报告,而不是6个报告(每位标志一个)。 我正在尝试编写一个动态查询,以根据@UserChoice参数构造HAVING子句。 我在想@UserChoice可以设置为整数值(1、2、3、4、5或6),当用户单击6选1的选项按钮时。 我尝试通过CASE表达式执行此操作,如下所示,但它不起作用-查询不返回任何行。 这里正确的方法是什么?

HAVING  (
        (CASE WHEN @UserChoice =1 THEN 'dbo.tblDocumentFact.useCase1' END) = '1'
  OR    (CASE WHEN @UserChoice =2 THEN 'dbo.tblDocumentFact.useCase2' END) = '1' 
  OR    (CASE WHEN @UserChoice =3 THEN 'dbo.tblDocumentFact.useCase3' END) = '1' 
  OR    (CASE WHEN @UserChoice =4 THEN 'dbo.tblDocumentFact.useCase4' END) = '1' 
  OR    (CASE WHEN @UserChoice =5 THEN 'dbo.tblDocumentFact.useCase5' END) = '1' 
  OR    (CASE WHEN @UserChoice =6 THEN 'dbo.tblDocumentFact.useCase6' END) = '1' 
        )

您需要稍微改一下逻辑:

HAVING
    (@UserChoice = 1 AND 'dbo.tblDocumentFact.useCase1' = '1') OR
    (@UserChoice = 2 AND 'dbo.tblDocumentFact.useCase2' = '2') OR
    (@UserChoice = 3 AND 'dbo.tblDocumentFact.useCase3' = '3') OR
    (@UserChoice = 4 AND 'dbo.tblDocumentFact.useCase4' = '4') OR
    (@UserChoice = 5 AND 'dbo.tblDocumentFact.useCase5' = '5') OR
    (@UserChoice = 6 AND 'dbo.tblDocumentFact.useCase6' = '6');

CASE表达式不能以您使用的方式使用,因为THENELSE内容必须是文字值,而不是逻辑条件。

为了进一步说明Tim的帖子下的评论,我认为它无法解决的原因是因为您的案例发出的字符串包含列名而不是列值

HAVING
  CASE WHEN @UserChoice = 1 THEN dbo.tblDocumentFact.useCase1 END = 1
  OR CASE WHEN @UserChoice = 2 THEN dbo.tblDocumentFact.useCase2 END = 1
 ...

它甚至可以清除此问题:

在1时dbo.tblDocumentFact.useCase1时有@UserChoice案例2时dbo.tblDocumentFact.useCase2 ... END = 1

问题(我相信;至少在sql server中,对SSRS不太完全确定)是当您说:

CASE WHEN @UserChoice = 1 THEN 'dbo.tblDocumentFact.useCase1' END = '1'

您的情况是发出文字字符串dbo.tblDocumentFact.useCase1而不是该行上该列的值。 当然,此文字字符串从不等于1的文字字符串

总的来说,我更喜欢蒂姆的解决方案。 我认为查询优化器将更有可能在该格式的位列上使用索引,但是请注意,使用OR可能会导致sql server忽略索引。 在我的老地方,DBA经常重写如下查询:

SELECT * FROM Person WHERE FirstName = 'john' OR LastName = 'Smith'

变成这个:

SELECT * FROM Person WHERE FirstName = 'john' 
UNION
SELECT * FROM Person WHERE LastName = 'Smith'

因为当我们使用OR时,服务器不会将FirstName上的索引和LastName上的其他索引合并,但是它将使用UNION形式的两个索引并行执行

可以考虑将这些位标志组合为一个整数,作为二进制2的补码(如果您希望通过搜索3来表示用户选择1和2,或者通过搜索42来表示选项2和4和6 [2, ^(2 -1)+ 2 ^(4-1)+ 2 ^(6-1)])或仅是一个整型,您可以将其与@userChoice进行比较并为其建立索引

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM