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



我的一个表包含 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 报表的数据集。 与其有 6 个报告,每个位一个标志,我希望有 1 个带有 @UserChoice 输入参数的报告。 我正在尝试编写一个动态查询,以根据 @UserChoice 参数构建 HAVING 子句。 我认为当用户单击 1-of-6 选项按钮时,@UserChoice可以设置为整数值(1、2、3、4、5 或 6(。 我尝试通过如下所示的 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
...

它甚至可能会清理到这个:

拥有 案例@UserChoice 当 1 则 dbo.tblDocumentFact.useCase1 当 2 则 dbo.tblDocumentFact.useCase2 ... 结束 = 1

问题(我相信;至少在sql服务器中,不完全确定SSRS(是当你说:

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

发出文本字符串的情况dbo.tblDocumentFact.useCase1不是该行上该列的值。当然,这个文字字符串永远不会等于1的文字字符串

总的来说,我更喜欢蒂姆的解决方案;我认为查询优化器更有可能以这种形式对位列使用索引,但请注意,使用 OR 可能会导致 sql 服务器忽略索引;我以前住的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^(2 -1( + 2^(4-1( + 2^(6-1(](说出用户选择 1 和 2,或者只是一个可以直接与 @userChoice 进行比较的整数, 并为其编制索引