2017-07-20 11 views
2

私は同じ複雑なwhere節を持つselect文の2つのタイプを持っています。同じwhere句を持つ複数のselectクエリ

1 - 返し取引詳細データ第二

select field_1, field_2, field_3, ... , field_30 from my_table where my_where_clause 

から戻り

select distinct field_1, field_2, field_8 from my_table where my_where_clause 

書を別々に呼ばれている(明確な)商人によってグループ化されたトランザクションデータ。

私は私のコードを簡素化し、それが可能だが、私は、動的SQLを使用したくない、動的SQLでのパフォーマンスを失うことなく、両方の文で、この複雑なwhere句

を繰り返さないようにしたいです。

提案がありますか?

+0

動的SQLはオプションかもしれません – SomeJavaGuy

+0

はい、ですが、私は動的SQLを避けたいです – mariami

+1

2番目は最初のものから派生するので、最初のものを一時テーブルに挿入して、それをオプションにすることができます。 –

答えて

1

だからあなたは、ビューまたは関数、Eには、この文をカプセル化することができグラム,:

create or replace view view_1 as 
    select field_1, field_2, field_3, ... , field_30 
    from my_table 
    where my_where_clause 

次に2番目のクエリは、このクエリを使用していることを言っ

select distinct * from view_1; 
+0

where句に多くのパラメータがあるため、VIEWを使用できません。私は関数を使用することはできません。なぜなら、この場合、サブ関数でCursorを返さなければならず、メイン関数でそれをループする必要があるからです。 – mariami

+0

ありがとう、私はいくつかの詳細を追加しました。 – mariami

+0

私は私のコードを単純化したいので、両方のステートメントで複雑な場所を書く必要はありません。これらのクエリはほぼ同じです。 – mariami

0

可能性がありjavaから。これを試して。

create or replace function get_cursor(p_type varchar2 default null/* other paramethers*/) return sys_refcursor 
is 
result_curosr sys_refcursor; 
begin 
open result_curosr for 'select '||p_type||' object_type,status from user_objects' /* where clausele */ ; 
return result_curosr; 
end; 

これをjavaから使用します。

Connection con = ... 
    CallableStatement callableStatement = con.prepareCall("declare c sys_refcursor; begin ? := get_cursor(?); end ; "); 

    callableStatement.registerOutParameter(1, OracleTypes.CURSOR); 

    callableStatement.setString(2, "Distinct"); // for distinct 
or 
    callableStatement.setNull(2, OracleTypes.VARCHAR); // for full results 
    callableStatement.executeUpdate(); 
    ResultSet rs = (ResultSet) callableStatement.getObject(1); 
    while(rs.next()) { 
     System.err.println(rs.getString(1)); 
    } 
    rs.close(); 

     con.close(); 

その他の解決策。 もう1つのパラメータを追加し、クエリのすべての列を使用して簡単な重複排除を実行します。しかし、私には利点はありません。

select object_type,status from 
(select object_type,status, row_number() over(partition by object_type,status order by 1) rn from user_objects /* your_where_clusue */ 
) where rn = case when 'DISTIINCT'/* <- paramete here :isDistinct */ = 'DISTIINCT' then 1 else rn end; 
+0

これは動的SQLを使用するソリューションです。私は動的SQLを使用したくない – mariami

+0

[OK]を、ダイナミックSQLでは、単純なクエリが、パフォーマンスがおそらく悪化します。 –

2

提案:あなたはSETS式をグループ化してみてください。 GROUP BY句内に作成するグループのセットを選択的に指定することができます。しかし、それが返されますあなたの場合は

では、1から30までのすべてのフィールドのセットで2セット、一つのグループを指定することができますし、https://docs.oracle.com/cd/E40518_01/server.761/es_eql/src/reql_aggregation_grouping_sets.html

リンク - フィールド1,2 & 8. のための別のセット単一の結果セットに両方のグループの出力があり、これがデザインに収まるかどうかは不明です。

0

複数行の文字列、別の引用符、およびテンプレートを使用すると、動的SQLをより読みやすくすることができます。

declare 
    v_select varchar2(32767); 
    v_where varchar2(32767); 
    v_code varchar2(32767) := ' 
      ##SELECT## 
      ##WHERE## 
    '; 
begin 
    --Populate the clauses. 
    if ... then 
     v_select := 'select field_1, field_2, field_3, ... , field_30 from my_table'; 
    else 
     v_select := 'select distinct field_1, field_2, field_8 from my_table'; 
    end if; 

    if ... then 
     v_where := 
     q'[ 
      where field_1 = 'foo' 
       and field_2 = :bind1 
       ... 
     ]'; 
    else 
     v_where := 
     q'[ 
      where field_2 = 'bar' 
       and field_2 = :bind2 
       ... 
     ]'; 
    end if; 

    --Fill in the code. 
    v_code := replace(v_code, '##SELECT##', v_select); 
    v_code := replace(v_code, '##WHERE##', v_where); 

    --Print the code to check the formatting. Remove after testing. 
    dbms_output.put_line(v_code); 

    --Run it. 
    execute immediate v_code using ...; 
end; 
/

完全ではありませんが、醜い連結を防止します。動的SQLを回避するために必要なアンチパターンよりもずっと優れています。ほとんどの言語で、多態性やリフレクションなどの機能は動的コードより優れています。 PL/SQLはこれらの拡張機能を適切にサポートしていないため、通常はコードを文字列として構築する方がよいでしょう。

関連する問題