我有一个包含6个参数的报告。所有参数都必须是可选的,3必须是多值的。其中一个可选参数是下拉列表,其余参数在文本框中手动键入。 当存在多个@VendorNum值和一个@FullJA值时,下面的Where子句可以工作,但无论@VendorNum计数如何,都会失败多个@FullJA值。
参数: @VendorNum - 由用户手动键入(空格分隔) - 可选,可以是多值的 @FullJA - 由用户手动键入(空格分隔) - 可选,可以是多值的 @BU - 可选,可以是多值 - 当@JA被填充时,这将自动填充,如果未填充@JA,则它是所有选中的下拉列表。 @ JA3 - 由用户键入 - 可选的单值 @StartDate和@EndDate - 可选的单个值
select * from some_table
WHERE
/*FULL JA*/
(
SUBSTRING(VendorNum, PATINDEX('%[^0]%', VendorNum + '.'), LEN(VendorNum)
) IN (@VendorNum)
AND LEFT(JA, 7) IN (@FullJA)
AND BU IN(@BU)
AND @JA3 IS NULL
)
OR
/*DATE RANGE*/
(
SUBSTRING(VendorNum, PATINDEX('%[^0]%', VendorNum + '.'), LEN(VendorNum)
) IN (@VendorNum)
AND LEN(ISNULL(CONVERT(VARCHAR(20), Cleared_When), '0')) >= @ClearedOnly
AND ad.Audit_Publish_Date >= ISNULL(@StartDate, '2015-01-01')
AND ad.Audit_Publish_Date <= ISNULL(@EndDate, '2025-12-31')
AND BU IN (@BU)
AND @FullJA IS NULL
AND @JA3 IS NULL
)
/*BUS UNIT AND JA3*/
OR (
SUBSTRING(VendorNum, PATINDEX('%[^0]%', VendorNum + '.'), LEN(VendorNum)
) IN (@VendorNum)
AND BU IN (@BU)
AND ad.Audit_Publish_Date >= ISNULL(@StartDate, '2015-01-01')
AND ad.Audit_Publish_Date <= ISNULL(@EndDate, '2025-12-31')
AND LEFT(JA, 3) = (@JA3)
AND @FullJA IS NULL
)
/*BUS UNIT ONLY*/
OR (
SUBSTRING(VendorNum, PATINDEX('%[^0]%', VendorNum + '.'), LEN(VendorNum)
) IN (@VendorNum)
AND BU IN (@BU)
AND ad.Audit_Publish_Date >= ISNULL(@StartDate, '2015-01-01')
AND ad.Audit_Publish_Date <= ISNULL(@EndDate, '2025-12-31')
AND @JA3 IS NULL
AND @FullJA IS NULL
)
@FullJA和@VendorNum的数据集参数值都是 = IIF(InStr(参数!FullJA.Value,“”)&gt; 0,SPLIT(参数!FullJA.Value,“”),参数!FullJA.Value)并且所有参数都设置为NOT多值,允许空值。
非常感谢任何帮助。我为这个项目写了200多份报告,这是唯一一个真正磨练我的齿轮!
谢谢!
答案 0 :(得分:0)
我会通过构建一些临时表/表变量,保存潜在的多值变量,然后加入这些表来解决这个问题。这样做的好处是,在省略变量的情况下,您可以插入所有可能的值。因此,如果给定变量,您将拆分字符串并将它们放入那些表(this example中的某些行)中,否则只需执行insert into
来填充临时表/表变量。
对于分割功能,我更喜欢这样的东西:
create FUNCTION [dbo].[Split] (@sep VARCHAR(32), @s VARCHAR(MAX))
RETURNS TABLE
AS
RETURN
(
SELECT r.value('.','VARCHAR(MAX)') as Item
FROM (SELECT CONVERT(XML, N'<root><r>' + REPLACE(REPLACE(REPLACE(@s,'& ','& '),'<','<'), @sep, '</r><r>') + '</r></root>') as valxml) x
CROSS APPLY x.valxml.nodes('//root/r') AS RECORDS(r)
)
GO
GRANT SELECT
ON OBJECT::[dbo].[Split] TO PUBLIC
AS [dbo];
然后我会使用类似的东西将这些变量放入表中(我的分隔符是“,”):
select ltrim(rtrim(ppl.Item)) as PersonName
into #gppl
from dbo.Split(', ', @PersonListForCompare) as ppl
你会做更多的事情:
select ltrim(rtrim(vnd.Item)) as VendorNum
into #vendorNums
from dbo.Split(', ', @VendorNum) as vnd
然后你就像其他任何桌子一样加入那个临时表。用它来限制你的结果。在您的情况下,如果他们没有给您任何输入,您想要(可能)放入所有供应商。所以,你会做类似的事情:
create table #vendorNums (VendorName varchar(64)) --I have no idea, here, what this data looks like
if @VendorNum is not null and datalength(@VendorNum) > 0
insert into into #vendorNums (VendorNum)
select ltrim(rtrim(vnd.Item))
from dbo.Split(', ', @VendorNum) as vnd
else
insert into into #vendorNums (VendorNum)
select VendorNum
from dbo.Vendors
那就是说,我认为您可以直接将select from dbo.Split
用作连接中的表,而不是将其放入临时表中。唯一的问题是你必须确保你有到分裂的数据,否则你将有一堆组合来获得正确的空参数匹配填好的。