2017-07-31 10 views
0

私は3つのテーブルを結合しようとしていますが、私はIF ELSEなしで次のSQLを持っています。Oracle SQL IF ELSEをUPDATE文に挿入するにはどうすればよいですか?

update transaction t 
set t.lid= (
select l.id from list l 
inner join distance d 
on l.ueid=d.ueid 
inner join transaction t2 
on t2.id=d.id 
) 

唯一の問題は

select l.id from list l 
    inner join distance d 
    on l.ueid=d.ueid 
    inner join transaction t2 
    on t2.id=d.id 

ひとつ返す値を超えると、私はt.gidに割り当てることができませんでしたステートメントです。私たちのビジネスルールでは、複数の値を返す場合、t.gidをnullに設定する必要があります。内部SELECT文が複数の値を返す場合、nullを返すには、このsqlのelse文をどのように組み込むことができますか?私はネット上の他の投稿を見てきましたが、ほとんどが手続きまたは関数です。

EDIT:

基本的な考え方は、l.idから上場テーブル1つの値のみを返す場合、内側はに参加した後、すなわち(トランザクションテーブル上のすべての行を更新することです距離テーブル)。複数の値が返された場合は、nullとして更新する必要があります。だから私はtまたはt2だけを使うべきかどうかは完全にはわかりません。

+0

アップデートしているtとサブクエリとの間には相関関係がないようです。もしt2が必要な場合は、これは一度だけのアップデートです。見る?また、いくつかのサンプルデータと期待される結果が有用かもしれません。そして、 'uid'は予約語です。本当に引用符で囲まれた識別子なのですか? –

+0

@AlexPoole私の質問が更新されました(編集してください)。 uidはタイプミスでした。それはueidです。 – WowBow

答えて

2

あなたはIDごとに値の集計数をチェックするためにa case expressionを使用することができます。

select t2.id, case when count(l.id) > 1 then null else max(l.id) end as lid 
from list l 
inner join distance d on l.ueid=d.ueid 
inner join transaction t2 on t2.id=d.id 
group by t2.id 

そしてと相関し、サブクエリとしてその使用 - 例えば - IDを両方transactionのテーブルから:

update transaction t 
set t.lid= (
    select case when count(l.id) > 1 then null else max(l.id) end as lid 
    from list l 
    inner join distance d on l.ueid=d.ueid 
    inner join transaction t2 on t2.id=d.id 
    where t2.id = t.id 
    group by t2.id 
) 

ここで、相関はwhere t2.id = t.id節で行われています。それはあなたがやっているチェックされている場合は、おそらく本当に全くt2を望んでいないが:

update transaction t 
set t.lid= (
    select case when count(l.id) > 1 then null else max(l.id) end as lid 
    from list l 
    inner join distance d on l.ueid=d.ueid 
    where d.id = t.id 
    group by d.id 
) 

where d.id = t.idで今相関します。

あなたはカウントに同じvalue, and in that case still want to use that single repeated value instead of null, then you can add a distinct`の複数のインスタンスをいただく場合がございます。

から動作するように何のサンプルデータ、および無予想される結果、うまくいけば、整合が存在しないテストされていないよう
update transaction t 
set t.lid= (
    select case when count(distinct l.id) > 1 then null else max(l.id) end as lid 
    from list l 
    inner join distance d on l.ueid=d.ueid 
    where d.id = t.id 
    group by d.id 
) 

あなたの説明で...

また、複数の一致がある場合だけでなく、サブクエリに一致する値がない場合、既存のtransaction.lidの値をnullに更新することにも注意してください。そうでない場合は、exists句を使用して、更新する行を制限するフィルタを追加できます。 mergeを使用することもできますが、updateはおそらくもっと簡単で明瞭です。

+0

これは私にとってすてきな解決策に見えます。 SQLが実行されてから30分経過しています。トランザクションテーブルには100万行あります。これをテストする方法がありますか?ありがとう。 – WowBow

+1

'mod(ID、100000)= 0の部分を使って、より小さな行セットをテストすることができます。 mod(id、10000)でサンプルサイズを簡単に増やすことができます。mod(id、1000000)などでサンプルサイズを小さくすることができます。 – zundarz

+1

@zundarzより簡単な方法は、 "rownum <11"あなたが選んだ番号)。これは、SQL文が動作する行数を制限する標準のOracleメソッドです。私は通常select文でそれを使用しています。したがって、私が "煙を吹く"ことを確実にするために、私はupdate文でそれをテストしました。 –

関連する問題