Запрос множественного выбора с тем же предложением where

У меня есть два типа оператора select с таким же сложным предложением where.

One - возвращает подробные данные транзакции

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

Заявления называются отдельно.

Я хочу упростить мой код и не повторять это сложное предложение where в обоих операторах без потери производительности

В динамическом SQL это возможно, но я не хочу использовать динамический SQL.

Какие-либо предложения?

4 ответа

Предложение: вы можете попробовать выражение GROUPING SETS. Это позволяет вам выборочно указывать набор групп, которые вы хотите создать в предложении GROUP BY. В

В вашем случае вы можете указать 2 набора: одна группа за набор для всех полей от 1 до 30, а другая группа для полей 1,2 и 8. Ссылка - https://docs.oracle.com/cd/E40518_01/server.761/es_eql/src/reql_aggregation_grouping_sets.html

Тем не менее, он вернет выходные данные обеих групп в одном наборе результатов, не уверен, что это вписывается в ваш дизайн.

Таким образом, вы можете заключить это утверждение в представление или функцию, например,

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

Тогда ваш второй запрос может быть

 select distinct * from view_1;

Вы сказали, что используете этот запрос из 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();

Другое решение. Добавьте еще один параметр и выполните простую дедупликацию, используя все столбцы из запроса. Но я не вижу никаких преимуществ.

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;

Вы можете сделать динамический 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 не имеет хорошей поддержки для этих расширенных функций, поэтому обычно лучше построить код в виде строки.

Другие вопросы по тегам