Oracle - 根据不同来源的不同行数进行减法

时间:2015-07-13 11:34:25

标签: sql oracle

我基本上有3个不同的select语句,它们根据键检索不同的行数。我想做减法,这样就不会丢掉任何记录。即使2个select语句返回null,我仍然会通过将它们设置为0来减去。

例如,

irb(main):001:0> require_relative 'lib/tracky'
LoadError: cannot load such file -- tracky/version
    from /home/matheus/.rbenv/versions/2.2.2/lib/ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in `require'
    from /home/matheus/.rbenv/versions/2.2.2/lib/ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in `require'
    from /home/matheus/Ruby/tracky/lib/tracky.rb:1:in `<top (required)>'
    from (irb):1:in `require_relative'
    from (irb):1
    from /home/matheus/.rbenv/versions/2.2.2/bin/irb:11:in `<main>'

在上面的例子中,我看到的是,由于WHERE子句条件,最终结果只返回5个记录的较小子集。我如何能够检索所有10个记录而不是较小的子集。理想情况下,我想要的是10条记录,其中那些匹配由(+, - )评估的WHERE CLAUSE和那些不匹配的记录也被设置为0进行评估。如果C得到记录而A,B没有,那么它将是c.exp_val +(0-0),A,B被设置为0.

2 个答案:

答案 0 :(得分:3)

您可以使用full outer join

SELECT COL1, COL2, COL3, (C.EXP_VAL + (A.EXP_VAL-B.EXP_VAL)) AS EXP_VAL
FROM (SELECT * FROM A WHEN KEY = 1 AND CATE_TYPE=1) A full outer join
     (SELECT * FROM B WHERE KEY =1 AND CATE_TYPE=2) B
     ON A.KEY = B.KEY AND
        A.COL1 = B.COL1 full outer join
     (SELECT * FROM C WHERE KEY=1 AND CATE_TYPE=3) C 
     ON C.KEY = COALESCE(A.KEY, B.KEY) AND
        C.COL1 = COALESCE(A.COL1, B.COL1);

如果您知道第三个子查询的行数最多,则可以重新排列子查询并使用LEFT JOIN

此外,永远不要在FROM子句中使用逗号。始终使用明确的JOIN

另请注意,不匹配表格中的值为NULL,而非0。如果您需要0,请使用COALESCE()

答案 1 :(得分:2)

正如戈登已经表明的那样,你通过使用全外连接获得所有记录。要使其可读,请使用USING子句,而不是ON:

select 
  col1, nvl(c.exp_val,0) + nvl(a.exp_val,0) - nvl(b.exp_val,0) as exp_val
from 
  (select * from a when key = 1 and cate_type = 1) a
full outer join 
  (select * from b when key = 1 and cate_type = 2) b using (col1)
full outer join 
  (select * from c when key = 1 and cate_type = 3) c using (col1);

链接所有记录的列是Col1显式(因为它在USING子句中)加上Key隐式(因为它在所有查询中设置为相同的值)。如果您愿意,可以将Key添加到USING子句using(key,col1)。它不会改变任何东西并且是多余的,但您可能认为它更具可读性。添加或离开它,这取决于你。