所以我想在Oracle SQL DB中比较两个支付表。我想比较使用地点和发票以及总付款的总付款。它更复杂,但基本上是:
select
tbl1.location,
tbl1.invoice,
Sum(tbl1.payments),
Sum(tbl2.payments)
From
tbl1
left outer join tbl2 on
tbl1.location = tbl2.location
and tbl1.invoice = tbl2.invoice
group by
(tbl1.location,tbl1.invoice)
我想要左外连接,因为除了比较付款金额外,我想查看tbl1中可能不存在于tbl2中的所有订单。
问题在于,两个表中的每个订单(位置和发票)都有多个记录(不一定是相同数量的记录,即tbl1中的2个到tbl2中的1个,反之亦然)但总付款每个订单(地点和发票)应匹配。所以只是直接加入给我一个笛卡尔积。
所以我想我可以做两个查询,首先按商店和商店汇总付款总额。每个发票,然后对这些结果进行联接,因为在汇总结果中,每个订单(商店和发票)只有一条记录。但我不知道该怎么做。我已经尝试了几个子查询,但似乎无法动摇笛卡尔积。我希望能够在一个查询中执行此操作,而不是创建表并加入这些表,因为这将持续进行。
提前感谢您的帮助。
答案 0 :(得分:1)
您可以使用With
语句创建两个查询,然后按照您的说法加入。我会放下sintaxe,如果你需要更多的帮助,请问。那是因为你没有提供你的桌子的完整细节。所以我会猜测我的答案。
WITH tmpTableA as (
select
tbl1.location,
tbl1.invoice,
Sum(tbl1.payments) totalTblA
From
tbl1
group by
tbl1.location,
tbl1.invoice
),
tmpTableB as (
select
tbl2.location,
tbl2.invoice,
Sum(tbl2.payments) totalTblB
From
tbl2
group by
tbl2.location,
tbl2.invoice
)
Select tmpTableA.location, tmpTableA.invoice, tmpTableA.totalTblA,
tmpTableB.location, tmpTableB.invoice, tmpTableB.totalTblB
from tmpTableA, tmpTableB
where tmpTableA.location = tmpTableB.location (+)
and tmpTableA.invoice = tmpTableB.invoice (+)
(+)
运算符是Oracle数据库的left join
运算符(当然,如果您愿意,可以使用LEFT JOIN语句)
答案 1 :(得分:0)
对不起,我的第一个回答是错误的。感谢您提供sqlfiddle,MT0。
我错过的一点是你需要首先总结每张桌子上的付款,所以每张桌子只留下一行,然后加入。这就是MT0在他的陈述中所做的。
如果您想要一个看起来更“对称”的解决方案,请尝试:
select A.location, A.invoice, B.total sum1, C.total sum2
from (select distinct location, invoice from tbl1) A
left outer join (select location, invoice, sum(payments) as total from tbl1 group by location, invoice) B on A.location=B.location and A.invoice=B.invoice
left outer join (select location, invoice, sum(payments) as total from tbl2 group by location, invoice) C on A.location=C.location and A.invoice=C.invoice
导致
LOCATION INVOICE SUM1 SUM2
a 2 3 2
a 1 5 3
b 1 1 5
b 2 1 (null)
答案 2 :(得分:0)
另外两个选择:
Oracle 11g R2架构设置:
CREATE TABLE tbl1 ( id, location, invoice, payments ) AS
SELECT 1, 'a', 1, 1 FROM DUAL
UNION ALL SELECT 2, 'a', 1, 1 FROM DUAL
UNION ALL SELECT 3, 'a', 1, 1 FROM DUAL
UNION ALL SELECT 4, 'a', 1, 1 FROM DUAL
UNION ALL SELECT 5, 'a', 1, 1 FROM DUAL
UNION ALL SELECT 6, 'a', 2, 1 FROM DUAL
UNION ALL SELECT 7, 'a', 2, 1 FROM DUAL
UNION ALL SELECT 8, 'a', 2, 1 FROM DUAL
UNION ALL SELECT 9, 'b', 1, 1 FROM DUAL
UNION ALL SELECT 10, 'b', 2, 1 FROM DUAL;
CREATE TABLE tbl2 ( id, location, invoice, payments ) AS
SELECT 1, 'a', 1, 1 FROM DUAL
UNION ALL SELECT 2, 'a', 1, 1 FROM DUAL
UNION ALL SELECT 3, 'a', 1, 1 FROM DUAL
UNION ALL SELECT 4, 'a', 2, 1 FROM DUAL
UNION ALL SELECT 5, 'a', 2, 1 FROM DUAL
UNION ALL SELECT 6, 'b', 1, 1 FROM DUAL
UNION ALL SELECT 7, 'b', 1, 1 FROM DUAL
UNION ALL SELECT 8, 'b', 1, 1 FROM DUAL
UNION ALL SELECT 9, 'b', 1, 1 FROM DUAL
UNION ALL SELECT 10, 'b', 1, 1 FROM DUAL;
查询1 :
这个使用相关的子查询来计算第二个表的总数:
SELECT location,
invoice,
SUM( payments ) AS total_payments_1,
COALESCE( (SELECT SUM( payments )
FROM tbl2 i
WHERE o.location = i.location
AND o.invoice = i.invoice),
0 ) AS total_payments_2
FROM tbl1 o
GROUP BY
location,
invoice
ORDER BY
location,
invoice
<强> Results 强>:
| LOCATION | INVOICE | TOTAL_PAYMENTS_1 | TOTAL_PAYMENTS_2 |
|----------|---------|------------------|------------------|
| a | 1 | 5 | 3 |
| a | 2 | 3 | 2 |
| b | 1 | 1 | 5 |
| b | 2 | 1 | 0 |
查询2 :
这个使用命名子查询预先计算表1的总数,然后使用第二个表执行LEFT OUTER JOIN
,并包括组中表1的总数。
如果没有任何索引,从解释计划中,查询1似乎效率更高,但您的索引可能意味着优化程序找到了更好的计划。
WITH tbl1_sums AS (
SELECT location,
invoice,
SUM( payments ) AS total_payments_1
FROM tbl1
GROUP BY
location,
invoice
)
SELECT t1.location,
t1.invoice,
t1.total_payments_1,
COALESCE( SUM( t2.payments ), 0 ) AS total_payments_2
FROM tbl1_sums t1
LEFT OUTER JOIN
tbl2 t2
ON ( t1.location = t2.location
AND t1.invoice = t2.invoice)
GROUP BY
t1.location,
t1.invoice,
t1.total_payments_1
ORDER BY
t1.location,
t1.invoice
<强> Results 强>:
| LOCATION | INVOICE | TOTAL_PAYMENTS_1 | TOTAL_PAYMENTS_2 |
|----------|---------|------------------|------------------|
| a | 1 | 5 | 3 |
| a | 2 | 3 | 2 |
| b | 1 | 1 | 5 |
| b | 2 | 1 | 0 |