0

パラメーターをさまざまなデータ型に使用できるように、複数の SQL Server クエリを 1 つのクエリに凝縮しようとしています。これらのタイプは、日付、数値、または文字列です。パラメータは @SearchValue と呼ばれます。

厳密に型指定された DataSet には、以下に示す 3 つのクエリがあります。

これは VB.Net コード ビハインド ファイルを使用した ASP.Net 用ですが、この質問は ASP.Net 以外にも適していると思います。

ユーザーが検索 TextBox に日付を入力した場合は、これを呼び出します。

クエリ:

SELECT ID, PaymentAmount, PaymentDate, WhatWasPaymentFor
  FROM     Payments
 WHERE     (ParentID = @ParentID) AND 
           (PaymentDate = @SearchValue)

日付検索クエリの VB.Net コード ビハインドからの呼び出し:

tblObject = theTableAdapter.GetDataByPaymentDate(dcmParentsId, TextBoxSearch.Text)

If tblObject.Count() > 0 Then
   GridViewSummary.DataSource = tblObject
   GridViewSummary.DataBind()
End If

他のものは数字専用で、最後のものはその他すべてのものです。

これは数字専用です:

SELECT PaymentDate, PaymentAmount, WhatWasPaymentFor, ID
  FROM Payments
 WHERE (ParentID = @ParentID) AND
       (PaymentAmount = @SearchValue)

これは、他の 2 つのクエリでデータが見つからない場合に呼び出されます。

SELECT PaymentDate, PaymentAmount, WhatWasPaymentFor, ID
  FROM Payments
 WHERE (ParentID = @ParentID) AND
       ((WhatWasPaymentFor LIKE '%' + @SearchValue + '%') OR
        (@SearchValue = 'ALL'))

このコーディングはすべてそのまま機能します。日付以外の値で .GetDataByPaymentDate を呼び出そうとするとエラーが発生するため、この方法で行いました。

単一のクエリを使用して、日付、数字、および文字列による検索を処理する方法はありますか?

*更新*

すべてのサンプル クエリに感謝します。どのような結果が得られるかを確認するために、SQL Server Management Studio ですべてのサンプル クエリを試しています。

これはゴードンのクエリに基づいていますが、データは返されません。

DECLARE @SearchValue VARCHAR = '01/01/2012'
DECLARE @SearchType  VARCHAR = 'Dates' 
DECLARE @ParentID    INT = 3

SELECT ID, PaymentAmount, PaymentDate, WhatWasPaymentFor
  FROM Payments cross join
       (select @SearchValue as sv) const
 WHERE ParentID = @ParentID AND
       (case when @SearchType = 'Dates' and ISDATE(const.sv) = 1
                then (case when PaymentDate = CAST(const.sv AS datetime) then 'true' else 'false' end)
             when @SearchType = 'Numbers' and ISNUMERIC(const.sv) = 1
                then (case when PaymentAmount = cast(const.sv as Int) then 'true' else 'false' end)
             when @SearchType = 'Everything Else'
                then (case when WhatWasPaymentFor LIKE '%' + const.sv + '%' OR const.sv='ALL' then 'true' else 'false' end)
   end) = 'true'

これは gh9 のものに基づいており、データを引き出します。ありがとうgh9:

DECLARE @SearchValue VARCHAR = 'Books'
DECLARE @ParentID    INT = 3
DECLARE @PaymentDate DATETIME = NULL
DECLARE @PaymentAmount MONEY = NULL

SELECT ID, PaymentAmount, PaymentDate, WhatWasPaymentFor
  FROM Payments
  WHERE ParentID = @ParentID
    AND (@paymentDate is null OR PaymentDate = @Paymentdate)
    AND (@paymentAmount is null OR paymentAmount = @paymentAmount)
    AND ((@SearchValue is null OR 
    (WhatWasPaymentFor LIKE '%' + @SearchValue  + '%' OR @SearchValue='ALL'))
  )
4

3 に答える 3

1

これにより、searchvalueを必要なものにキャストする必要がないという利点が得られ、もう少し読みやすくなります。必要に応じて構文を変更しますが、重要なアイデアは、必要なデータ型にキャストするのではなく、SQLサーバー機能を使用してnullパラメーターと短絡ロジックを使用して強く型付けされたパラメーターを評価することです。

@ParentID  INT 
@PaymentAmount INT = NULL
@PaymentDate Datetime = null
@GenericSearchTerm varchar(100) = null  

AS
BEGIN
SELECT
  ID,
  PaymentAmount,
  PaymentDate,
  WhatWasPaymentFor
FROM Payments
WHERE @ParentID = @ParentID
  AND ( (@paymentDate is null OR PaymentDate = @Paymentdate))
        AND (@paymentAmount is null OR paymentAmount = @paymentAmount))
        AND ( @GenericSearchTerm is null OR ((WhatWasPaymentFor LIKE '%' + @GenericSearchTerm  + '%' OR @SearchValue='ALL'))

編集:@andriyMコメントごとに更新された回答

于 2013-01-14T20:32:34.833 に答える
0

これは Bstateham の回答に触発されたものですが、2 つの異なる方法で行います。まず、値をテーブルに格納し、定数から変数に変換します。case第二に、短絡を保証するため、を使用します。

これにより、次のような結果になります。

SELECT ID, PaymentAmount, PaymentDate, WhatWasPaymentFor
FROM Payments cross join
     (select @SearchValue as sv) const
WHERE @ParentID = @ParentID AND
      (case when @SearchType = 'datetime' and ISDATE(const.sv) = 1
            then (case when PaymentDate = CAST(const.sv AS datetime) then 'true' else 'false' end)
            when @SearchType = 'int' and ISNUMERIC(const.sv) = 1
            then (case when PaumentAmount = cast(const.sv as Int) then 'true' else 'false' end)
            when @SearchType = 'nvarchar'
            then (case when WhatWasPaymentFor LIKE '%' + const.sv + '%' OR const.sv='ALL' then 'true' else 'false' end)
       end) = 'true'

また、整数と日付への変換の検証チェックも追加しました (完全ではありませんが、役に立ちます)。また、タイプではなく、宛先フィールドの後に @SearchType という名前を付ける必要があります。ただし、タイプ名のバージョンを保持しています。

于 2013-01-14T20:28:35.080 に答える
0

('datetime'、'int'、または 'nvarchar') の可能な値を持つ @SearchType の 3 番目のパラメーターを追加し、それを WHERE 句で使用して、比較のために @SearchValue を適切な型にキャストするのはどうでしょうか。何かのようなもの:

SELECT
  ID,
  PaymentAmount,
  PaymentDate,
  WhatWasPaymentFor
FROM Payments
WHERE @ParentID = @ParentID
  AND (
        (@SearchType = 'datetime' AND PaymentDate = CAST(@SearchValue AS datetime))
        OR
        (@SearchType = 'int' AND PaymentAount = CAST(@SearchValue AS int))
        OR
        (@SearchType = 'nvarchar' AND 
          (WhatWasPaymentFor LIKE '%' + @SearchValue + '%' OR @SearchValue='ALL')
        );
于 2013-01-14T18:28:42.617 に答える