3

SSRS參數是一種痛苦。我希望能夠通過允許用戶訪問許多不同的參數並使其成爲可選項來重用報告以滿足許多不同的需求。SSRS參數。允許「全部」或「空」

所以,如果我在開始時的代碼,如:

Select * from mytable myt 
where myt.date between '1/1/2010' and '12/31/2010' 
and year(myt.date) = '2010' 
and myt.partnumber = 'XYZ-123' 

我想這些參數是可選的,所以我的第一次嘗試是使參數默認爲空,例如:

and (myt.partnumber = (@PartNumber) or (@PartNumber) is null) 

這有問題,因爲如果有問題的數據庫字段可以爲空,那麼您將刪除記錄,因爲null不等於null。

然後我用如下代碼:

DECLARE @BeginDate AS DATETIME 
DECLARE @EndDate AS DATETIME 
DECLARE @PartNumber AS VARCHAR(25) 
SET @Year = '..All' 
SET @BeginDate = '1/1/2005' 
SET @EndDate = '12/31/2010' 
SET @PartNumber = '..All' 
SET @Year = '..All' 

Select * from mytable myt 
where (myt.date between (@BeginDate) and (@EndDate)) 
and (year(myt.date) = (@Year) or (@Year) = '..All') 
and (myt.partnumber = (@PartNumber) or (@PartNumber) = '..All') 

這並不工作,因爲年(myt.date)是一個整數,@Year不是。

所以,這是我的問題。

  1. 如何讓我的日期可選?是簡單地將它們默認爲實際範圍外的日期的最好方法,所以我返回所有值?
  2. 處理null或'..All'選項以使我的查詢儘可能可讀並允許我的用戶擁有大多數數據類型的可選參數的最佳方法是什麼?我寧願不爲

回答

1

我喜歡你的第三個代碼塊使用空。看起來好像你的WHERE子句可以被修正以使用非int值。該AND子句年線應該是這樣的 - 不是我最好的T-SQL,但它應該讓你在正確的方向:

and 1 = CASE @Year WHEN '..All' THEN 1 ELSE CASE WHEN year (myt.date) = CONVERT (int, @Year) THEN 1 ELSE 0 END END 

這將讓你有」字符串值。 .All'或一個int值。要麼會匹配正確。你可以用partnumber做同樣的事情。

+0

我曾考慮過使用case語句,但問題是如果我有10個參數並且大多數是Case語句,SQL語句會變得非常冗長和混亂。 – DavidStein 2010-07-28 13:38:50

+1

你可以選擇年份和partnumber(如-1)的幻數,然後你不需要投射或轉換任何東西。這允許您使用第二個代碼塊。 – 2010-07-28 17:56:55

3

繼續並允許空值,表示不應用過濾器。然後,您可以使用以下命令:

SELECT * 
FROM mytable myt 
WHERE COALESCE(myt.date, '1/1/1900') between COALESCE(@BeginDate, myt.date, '1/1/1900') and COALESCE(@EndDate, myt.date, '1/1/1900') 
    AND COALESCE(YEAR(myt.date), -1) = COALESCE(@Year, YEAR(myt.date), -1) 
    AND COALESCE(myt.partnumber, -1) = COALESCE(@PartNumber, myt.partnumber, -1) 

總之,如果任何變量值爲NULL,然後比較列值本身,它有效地忽略了條件。更具體地說,當測試myt.date時,如果@BeginDate爲NULL,則將較低範圍值設置爲等於myt.date值。使用@EndDate值進行相同的替換。即使如果@BeginDate@EndDate都爲NULL,條件也是如此。

類似的方法也用於YEAR(myt.date)myt.partnumber。如果變量值爲NULL,則將列值與自身進行比較,總是爲true。

更新: 爲每個COALESCE添加一個默認值來處理列值爲NULL的情況。

+0

這不起作用,並且是我嘗試的第一件事情(在問題中提到)。原因是,如果我的某個字段可以爲空並且包含空值,那麼記錄不會被返回。 例如: AND myt.partnumber = COALESCE(@PartNumber,myt.partnumber) 如果myt.partnumber和@PartNumber都爲null,則聯接不會返回該記錄。 – DavidStein 2010-07-28 13:40:58

+1

大衛 - 我錯過了。但是,我還沒有放棄......還沒有。檢查每個COALESCE中有附加值的更新。這對你有幫助嗎? – bobs 2010-07-28 16:27:51

0

嘗試這樣,關鍵是要解決您的空參數值到代理空,也因爲SQL服務器支持短路評價,把空檢查一般應表現得更好。

Select * from mytable myt 
where (myt.date between (@BeginDate) and (@EndDate)) 
and (@Year IS NULL OR COALESCE(myt.date,'1900') = @Year) 
and (@PartNumber IS NULL OR ISNULL(myt.partnumber, '<NULL>') = (@PartNumber)