2012-01-27 16 views
1

現在、私のクエリのWHERE句で次のSQL文を使用するJavaで準備された文がありますが、これを制限する関数に書き直したいと思いますユーザパラメータはそれに渡され、おそらくより効率的になります。ヌル検索を含むwhere句の関数を使用する

(
    (USER_PARAM2 IS NULL AND 
    (COLUMN_NAME = nvl(USER_PARAM1, COLUMN_NAME) OR 
     (nvl(USER_PARAM1, COLUMN_NAME) IS NULL) 
    ) 
) 
    OR 
    (USER_PARAM2 IS NOT NULL AND COLUMN_NAME IS NULL) 
) 

USER_PARAM1とUSER_PARAM2は、ユーザーが準備したステートメントに渡されます。 USER_PARAM1は、この特定のCOLUMN_NAMEを検索するアプリケーションのユーザーを表します。ユーザーがこのパラメーターを含まない場合は、デフォルトでNULLになります。 USER_PARAM2は、ユーザーがこのCOLUMN_NAMEでNULL値のみの検索をリクエストできるようにするための方法でした。また、ユーザーによって渡された場合はUSER_PARAM2を 'true'に設定し、ユーザーが指定しなかった場合はNULLを設定するサーバーロジックもあります。

USER_PARAM2が宣言されている場合は、NULLのCOLUMN_NAME値のみが返されることになります。 USER_PARAM2が宣言されておらず、USER_PARAM1が宣言された場合は、COLUMN_NAME = USER_PARAM1のみが返されます。いずれのユーザー・パラメーターも宣言されていない場合、すべての行が戻されます。

誰でも私にこれを助けることができますか?事前に おかげで...

EDIT: ただ明確にするこれが私の現在のクエリが(..他のWHERE句の文なし)

SELECT * 
FROM TABLE_NAME 
WHERE (
    (USER_PARAM2 IS NULL AND 
    (COLUMN_NAME = nvl(USER_PARAM1, COLUMN_NAME) OR 
     (nvl(USER_PARAM1, COLUMN_NAME) IS NULL) 
    ) 
) 
    OR 
    (USER_PARAM2 IS NOT NULL AND COLUMN_NAME IS NULL) 
) 

に見える...これはどこ私が希望です方法です...に取得したいEDIT#2

SELECT * 
FROM TABLE_NAME 
WHERE customSearchFunction(USER_PARAM1, USER_PARAM2, COLUMN_NAME) 

: OKは、その別の同僚が、これで私を助けて...

CREATE OR REPLACE function searchNumber (pVal IN NUMBER, onlySearchForNull IN CHAR, column_value IN NUMBER) 
    RETURN NUMBER 
IS 
BEGIN 
    IF onlySearchForNull IS NULL THEN 
    IF pVal IS NULL THEN 
     RETURN 1; 
    ELSE 
     IF pVal = column_value THEN 
     RETURN 1; 
     ELSE 
     RETURN 0; 
     END IF; 
    END IF; 
    ELSE 
    IF column_value IS NULL THEN 
     RETURN 1; 
    ELSE 
     RETURN 0; 
    END IF; 
    END IF; 
END; 

...これは私の最初の試験で..

SELECT * 
FROM TABLE_NAME 
WHERE 1=searchNumber(USER_PARAM1, USER_PARAM2, COLUMN_NAME); 

を動作するようです...それで私が持っている唯一の問題は、私が始めた、複雑なSQL文の対 1)のパフォーマンス上の問題だろう。 2)各データタイプに同様の関数を作成する必要があります。 しかし、後者は私にはあまり問題ではありません。

EDIT#3 2012年2月1日

だから我々は、コード/クエリ清浄度がパフォーマンスを切り札機能ベースのアプローチを使用している間、私は、以下の選んだ解決策と一緒に行くことになりました。関数ベースのアプローチでは、純粋なSQLを使用するよりも悪化していることがわかりました。

皆さん、ありがとうございました。

EDIT#4 2012年2月14日

は、だから私は、@のdanihpのソリューションの明快さと@に仮想テーブルの概念を適用するアランのソリューションは、明快さとパフォーマンスの面で非常に素晴らしい全体的なソリューションを提供していることに気づい振り返ります。ここに私が今持っているものがあります

WITH params AS (SELECT user_param1 AS param, user_param2 AS param_nullsOnly FROM DUAL) 
SELECT * 
FROM table_name, params p 
WHERE (nvl(p.param_nullsOnly, p.param) IS NULL     --1) 
     OR p.param_nullsOnly IS NOT NULL AND column_name IS NULL --2) 
     OR p.param IS NOT NULL AND column_name = p.param   --3) 
     ) 
-- 1) Test if all rows should be returned 
-- 2) Test if only NULL values should be returned 
-- 3) Test if param equals the column value 

おかげさまで、提案とコメントをお寄せいただきありがとうございます。

+0

なぜ機能を変更するのですか?ネイティブSQLは、見た目が乱雑ですが、確かに優れたパフォーマンスを発揮します。 –

+0

実際に関数が必要な場合は、 "customSearchFunction"がvarchar2値(たとえばS/N)を返す必要があります。 customSearchFunction(USER_PARAM1、USER_PARAM2、COLUMN_NAME)= 'S' –

+1

関数を使用すると、文を評価するときにテーブル全体を強制的にスキャンする可能性があります。小さなテーブル(または小さなテーブルのジョイン)の場合、これは問題ではないかもしれませんが、大きなテーブルの場合は、パフォーマンスが大幅に向上する可能性があります。 YMMV。 –

答えて

2

共通テーブル式を使用して、パラメータを1回だけ渡し、必要な回数だけそれらを参照する簡単な方法があります。

WITH params AS (SELECT user_param1 AS up1, user_param2 AS up2 FROM DUAL) 
SELECT * 
FROM table_name, params p 
WHERE ((p.up2 IS NULL 
     AND (column_name = NVL(p.up1, column_name) 
       OR (NVL(p.up1, column_name) IS NULL))) 
     OR (p.up2 IS NOT NULL AND column_name IS NULL)) 

仮想テーブルを作成しています。ここで、列はパラメータであり、1行で作成されます。

これはまた、すべてのパラメータが同じ場所に収集され、任意の順序で(クエリに自然に表示される順序とは対照的に)指定できることを保証します。

これには、機能ベースのアプローチに比べて大きな利点がいくつかあります。まず、これはインデックスの使用を妨げません(@Bob Jarvisが指摘するように)。第2に、これは、関数に隠されるのではなく、クエリのロジックをクエリに保持します。

+0

ありがとう!速度の組み合わせと冗長なパラメータの排除のために、このアプローチが本当に好きです。 – hypno7oad

2

私のアプローチは、より高いパフォーマンスを持っている場合、私は知りませんが、それは最高の可読性があります

where 
(P_ALL_RESULTS is not null 
    OR 
    P_ONLY_NULLS is not null AND COLUMN_NAME IS NULL 
    OR 
    P_USE_P1 is not null AND COLUMN_NAME = USER_PARAM1 
) 

免責事項::前に答えあなたは次のようにクエリを書き直すことができ照会する2つのadditionalsパラメータを送信

OP質問の明確化

+1

最後の条件は、P_USE_P1がNULLではなく、COLUMN_NAME = USER_PARAM1 –

+0

@BD、修正されました。 – danihp

+0

免責事項:OP質問の明確化の前に回答します。 – danihp

関連する問題