Sql Oracle-根据不同来源的不同行数执行减法
我基本上有3个不同的select语句,它们根据一个键检索不同数量的行。我想做减法运算,这样就不会丢失任何记录。即使这两条select语句返回null,我仍然会通过将它们设置为0进行减法 比如说,Sql Oracle-根据不同来源的不同行数执行减法,sql,oracle,Sql,Oracle,我基本上有3个不同的select语句,它们根据一个键检索不同数量的行。我想做减法运算,这样就不会丢失任何记录。即使这两条select语句返回null,我仍然会通过将它们设置为0进行减法 比如说, 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, \\ RETURNS 5 ROWS (SELECT
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, \\ RETURNS 5 ROWS
(SELECT * FROM B WHERE KEY =1 AND CATE_TYPE=2) B, \\ RETURNS 5 ROWS
(SELECT * FROM C WHERE KEY=1 AND CATE_TYPE=3) C \\RETURNS 10 ROWS
WHERE A.KEY=B.KEY AND A.KEY=C.KEY AND A.COL1=B.COL1 AND A.COL1=C.COL1;
在上面的示例中,我看到的是,由于WHERE子句的条件,最终结果只返回5条记录中较小的子集。我如何能够检索所有10条记录,而不是较小的子集。理想情况下,我想要的是10条记录,匹配WHERE子句的记录由(+、-)计算,不匹配的记录也由设置为0计算。例如,如果C获得记录,而A、B没有,则将是C.exp_val+(0-0),其中A、B设置为0。您可以使用
完全外部联接
:
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);
如果知道第三个子查询的行数始终最多,则可以重新排列子查询,并使用左联接
此外,切勿在FROM
子句中使用逗号。始终使用显式JOIN
s
还要注意,不匹配表中的值将是
NULL
,而不是0
。如果您想要0
,那么使用COALESCE()
正如Gordon已经展示的那样,您可以通过使用完整的外部联接来获取所有记录。要使其可读,请使用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,col1)将键添加到USING子句
。它不会改变任何东西,而且是多余的,但是你可以认为它更可读。添加或保留,这取决于您。可能需要使用带NVL功能的左连接。是否可以找到不存在c记录的a或b记录?如果是这样的话,你想不想在你的结果中看到它?谢谢戈登,谢谢你!感谢Thorsten的支持@托尔斯滕。这是个好主意。我忘记了使用
修复了完全外部联接
的空值问题。