使用select in update

时间:2017-10-24 22:21:55

标签: sql oracle

所以,我有两张桌子,为了简单起见,我会为一个显示2列,而另一个只显示一列,但他们有更多的数据。

好的,所以,表格看起来像这样:

 _________________________________ 
|            table 1              |
+---------------------------------+
|    gas_deu         est_pag      |
+---------------------------------+
|     56857          (null)       |
|     60857          (null)       |
|     80857          (null)       |
+---------------------------------+

 ______________________
|      table 2         |
+----------------------+
|      gas_pag         |
+----------------------+
|       56857          |
|       21000          |
|       75857          |
+----------------------+

表1和表2可以使用id_edi和nr_dep(两个表中的相同名称)连接
这里发生的事情基本上如下:
在表1中,我有gas_deu,这是某人拥有的号码。
在表2中gas_pag是支付了多少,这意味着如果gas_deu已全额支付,gas_deu-gas_pag应该给0(或负数),如果部分支付了gas_deu则为正数 此外,表1中的某些行不在表2中,这意味着gas_deu根本没有支付。

我需要做的是用以下内容更新表1中的est_pag:
如果gas_deu-gas_pag< = 0(已支付债务)则将est_pag值更新为1
如果gas_deu-gas_pag> 0(部分支付)则将est_pag值更新为2
如果一行在表1中但在表2中没有,则根本没有支付,因此est_pag值将为3

我已经尝试了很多,我的意思是在更新中有很多代码,这些表有很多列,所以我不会发布我尝试的代码,因为它只会让人感到困惑
我主要尝试在更新集中以及更新的位置使用选择子查询。所有这些都总是给我单行错误,我知道这是因为它返回多个值,但我怎么做?我没有看到一种方法,我只得到一个查询值,只更新与债务状态相匹配的行。

使用case对我来说是合乎逻辑的选择,但它总是会返回多行(尝试制作一个(例如gas_deu-gas_pag< = 0然后1,其他est_pag结束),因为如果我能得到至少一个在那里的价值,它将是一个开始,但获得相同的多行问题)

任何帮助或建议都非常感谢,我已经尝试了我能想到的一切,并且在stackoverflow中有很多答案,但仍然无法解决问题 编辑:在更新后添加表1应该是什么样子

|            table 1              |
+---------------------------------+
|    gas_deu         est_pag      |
+---------------------------------+
|     56857               1       |
|     60857               2       |
|     80857               2       |
+---------------------------------+


更新2:

update table1
set est_pag=(select (case when (select min((case when gasto.gas_deu-
pago.gas_pag<=0 then 0 else null end))
from table2 pago full outer join gasto_comun_pruebaestpago gasto on 
pago.nr_dep=gasto.nr_dep
where gasto.nr_dep=pago.nr_dep and gasto.id_edi=pago.id_edi)=0 then 1 else 
null end)
from table2 pago full outer join gasto_comun_pruebaestpago gasto on 
pago.nr_dep=gasto.nr_dep
where gasto.nr_dep=pago.nr_dep and gasto.id_edi=pago.id_edi)
where est_pag is null;


这是我尝试过的众多代码之一。这个将所有值更改为1,这是因为min()在那里,只有一行,0和得到的情况检查,0 = 0所以一切都变为1.问题是,如果没有min(),select会执行我需要的操作,但是更新会再次抛出'单行子查询返回多行'错误

1 个答案:

答案 0 :(得分:0)

您可以通过左外连接进行更新。第二个表可能有多个同一帐户的付款(客户可能会进行部分付款),因此我首先按ID聚合第二个表。你没有为测试提供输入数据,所以在我的小测试中,我假设这些表匹配id(第一个表中的主键,第二个表中的外键 - 即使我没有写约束到表定义中。)

我编写更新的方式是,如果第二个表中没有帐户,则会分配3,但如果 存在,但NULL位于{{} 1}}列。 (如果该栏从一开始就被宣布为gas_pag,那将是最好的!)如果在这种情况下需要不同的处理,你没有说;它可以很容易地适应。

所以,这就是。

表创建

NOT NULL

更新声明

create table t1 ( id number, gas_deu number, est_pag number );

insert into t1
  select 101, 56857, null from dual union all
  select 104, 60857, null from dual union all
  select 108, 80857, null from dual
;

create table t2 ( id number, gas_pag number ) ;

insert into t2
  select 101, 56857 from dual union all
  select 104, 60000 from dual
;

select * from t1;

        ID    GAS_DEU    EST_PAG
---------- ---------- ----------
       101      56857           
       104      60857           
       108      80857           

select * from t2;

        ID    GAS_PAG
---------- ----------
       101      56857
       104      60000

CLEAN-UP

update 
  ( select est_pag, gas_deu, gas_pag 
    from   t1 left join 
           ( select id, sum(gas_pag) as gas_pag from t2 group by id ) x
             on t1.id = x.id
  )
set    est_pag = case when gas_deu <= gas_pag then 1
                      when gas_deu >  gas_pag then 2
                      else                             3
       end
;

select * from t1;

        ID    GAS_DEU    EST_PAG
---------- ---------- ----------
       101      56857          1
       104      60857          2
       108      80857          3