SQL Serverの魅力のように機能するクエリを作成しました。残念ながら、Oracleデータベースで実行する必要があります。私はそれを変換する方法についての解決策を求めてウェブを徹底的に探してきましたが、成功しませんでした:/
クエリはi SQLのようになります。
UPDATE tab1 SET budgpost_gr1=
CASE WHEN (budgpost in (1001,1012,50055)) THEN 'BP_GR_A'
WHEN (budgpost in (5,10,98,0)) THEN 'BP_GR_B'
WHEN (budgpost in (11,876,7976,67465))
ELSE 'Missing' END`
私の問題は、列budgetpost_gr1
およびbudgetpostは英数字であり、Oracleはリストを数字として表示したいようです。リストは、コンマ区切りリストとして事前定義された変数/パラメーターであり、クエリにダンプされるだけです。
実行するソリューションを手に入れました。それが最適であるかどうかわからない。私がやることは、 http://blogs.Oracle.com/aramamoo/2010/05/how_to_split_comma_separated_string_and_pass_to_in_clause_of_select_statement.html に従って文字列を分割することです
を使用して:select regexp_substr(' 1, 2 , 3 ','[^,]+', 1, level) from dual
connect by regexp_substr('1 , 2 , 3 ', '[^,]+', 1, level) is not null;
したがって、最終的なコードは次のようになります($bp_gr1'
は1,2,3
のような文字列です):
UPDATE TAB1
SET BUDGPOST_GR1 =
CASE
WHEN ( BUDGPOST IN (SELECT REGEXP_SUBSTR ( '$BP_GR1',
'[^,]+',
1,
LEVEL )
FROM DUAL
CONNECT BY REGEXP_SUBSTR ( '$BP_GR1',
'[^,]+',
1,
LEVEL )
IS NOT NULL) )
THEN
'BP_GR1'
WHEN ( BUDGPOST IN (SELECT REGEXP_SUBSTR ( ' $BP_GR2',
'[^,]+',
1,
LEVEL )
FROM DUAL
CONNECT BY REGEXP_SUBSTR ( '$BP_GR2',
'[^,]+',
1,
LEVEL )
IS NOT NULL) )
THEN
'BP_GR2'
WHEN ( BUDGPOST IN (SELECT REGEXP_SUBSTR ( ' $BP_GR3',
'[^,]+',
1,
LEVEL )
FROM DUAL
CONNECT BY REGEXP_SUBSTR ( '$BP_GR3',
'[^,]+',
1,
LEVEL )
IS NOT NULL) )
THEN
'BP_GR3'
WHEN ( BUDGPOST IN (SELECT REGEXP_SUBSTR ( '$BP_GR4',
'[^,]+',
1,
LEVEL )
FROM DUAL
CONNECT BY REGEXP_SUBSTR ( '$BP_GR4',
'[^,]+',
1,
LEVEL )
IS NOT NULL) )
THEN
'BP_GR4'
ELSE
'SAKNAR BUDGETGRUPP'
END;
より高速に実行する方法はありますか?
Budgetpostは英数字であると言いました。つまり、文字列との比較を探しています。パラメータを一重引用符で囲むようにしてください(Case式に最後のTHENがありません)。
UPDATE tab1
SET budgpost_gr1= CASE
WHEN (budgpost in ('1001','1012','50055')) THEN 'BP_GR_A'
WHEN (budgpost in ('5','10','98','0')) THEN 'BP_GR_B'
WHEN (budgpost in ('11','876','7976','67465')) THEN 'What?'
ELSE 'Missing'
END
to_number
を使用して、budgpost
を数値に変換します。
when to_number(budgpost,99999) in (1001,1012,50055) THEN 'BP_GR_A'
編集:9
に十分な数のto_number
があり、最大の予算投稿に一致することを確認してください。
数値以外の予算投稿がある場合、クエリの最後にwhere
句を使用してそれらを除外できます。
where regexp_like(budgpost, '^-?[[:digit:],.]+$')
「リストは、コンマ区切りリストとして事前定義された変数/パラメーターです」。あなたのクエリは実際には
UPDATE tab1 SET budgpost_gr1=
CASE WHEN (budgpost in ('1001,1012,50055')) THEN 'BP_GR_A'
WHEN (budgpost in ('5,10,98,0')) THEN 'BP_GR_B'
WHEN (budgpost in ('11,876,7976,67465'))
ELSE 'Missing' END`
その場合、文字列を取得してそれを数値のリストに解析する関数が必要です。
create type tab_num is table of number;
create or replace function f_str_to_nums (i_str in varchar2) return tab_num is
v_tab_num tab_num := tab_num();
v_start number := 1;
v_end number;
v_delim VARCHAR2(1) := ',';
v_cnt number(1) := 1;
begin
v_end := instr(i_str||v_delim,v_delim,1, v_start);
WHILE v_end > 0 LOOP
v_cnt := v_cnt + 1;
v_tab_num.extend;
v_tab_num(v_tab_num.count) :=
substr(i_str,v_start,v_end-v_start);
v_start := v_end + 1;
v_end := instr(i_str||v_delim,v_delim,v_start);
END LOOP;
RETURN v_tab_num;
end;
/
その後、次のような関数を使用できます。
select column_id,
case when column_id in
(select column_value from table(f_str_to_nums('1,2,3,4'))) then 'red'
else 'blue' end
from user_tab_columns
where table_name = 'EMP'
結合を使用して更新するために使用できる別の回避策があります。以下のこの例では、ルックアップ値を含めることでテーブルを非正規化することを前提としています(この場合、ユーザー名をテーブルに保存します)。更新には、名前を見つけるための結合が含まれており、出力は、検出される名前または検出されない名前をサポートするCASEステートメントで評価されます。この作業を行うための鍵は、結合から出てくるすべての列が一意の名前を持つようにすることです。サンプルコードで、b.user_nameがa.user_name列と競合し、一意の名前「user_user_name」でエイリアス化する必要があることに注意してください。
UPDATE
(
SELECT a.user_id, a.user_name, b.user_name as user_user_name
FROM some_table a
LEFT OUTER JOIN user_table b ON a.user_id = b.user_id
WHERE a.user_id IS NOT NULL
)
SET user_name = CASE
WHEN user_user_name IS NOT NULL THEN user_user_name
ELSE 'UNKNOWN'
END;