我确实有这样的查询,其中调用了多个总和子查询。 With子句似乎在这里不起作用。
select
a.id,
a.balance as main_balance,
(select sum(amount) from sub_account sa where sa.account_id = a.id) as sub_account_sum,
a.balance - (select sum(amount) from sub_account sa where sa.account_id = a.id) as diff
from accounts a
inner join sub_account sa on sa.account_id = a.id
where a.balance != (select sum(amount) from sub_account sa where sa.account_id = a.id)
and a.balance - (select sum(amount) from sub_account sa where sa.account_id = a.id) < 5000
and a.balance - (select sum(amount) from sub_account sa where sa.account_id = a.id) > -5000
and (select count(*) from sub_account sa where sa.account_id = a.id) > 1
子查询(select sum(amount) from sub_account sa where sa.account_id = a.id)
被调用5次。基本上,我想在每个地方用外观更好的东西代替它。
答案 0 :(得分:2)
为什么WITH子句不起作用?试试看。我删除了最后一条语句(在where子句中带有count(*),因为您正在执行内部联接,因此无论如何都不会满足条件。
WITH sub_account_sum_by_acct AS
(select account_id, sum(amount) as sub_account_sum from sub_account sa group by account_id)
SELECT
a.id,
a.balance as main_balance,
sa.sub_account_sum,
a.balance - sa.sub_account_sum as diff
FROM accounts a
JOIN sub_account_sum_by_acct sa on sa.account_id = a.id
where a.balance != sa.sub_account_sum
and a.balance - sa.sub_account_sum < 5000
and a.balance - sa.sub_account_sum > - 5000
答案 1 :(得分:1)
您可以使用窗口函数代替子查询:
select
id,
balance,
sub_account_sum
from (
select
a.id,
a.balance as main_balance,
sum(amount) over(partition by sa.account_id) as sub_account_sum,
count(*) over(partition by sa.account_id) as sub_account_cnt
from accounts a
inner join sub_account sa on sa.account_id = a.id
) t
where
balance != sub_account_sum
and abs(a.balance - sub_account_sum) < 5000
and sub_account_cnt > 1
答案 2 :(得分:0)
您还可以使用以下功能。我保持与您的SQL相同的格式,只是删除了多个子查询并使它们保持功能。逻辑与您的SQL相同。
WITH FUNCTION sa_acc(val VARCHAR2) RETURN VARCHAR2 IS
lv_val varchar2(20);
BEGIN
SELECT SUM(amount) into lv_val
FROM sub_account sa
WHERE sa.account_id = val;
return lv_val;
END;
SELECT a.id,
a.balance AS main_balance,
sa_acc(a.id) AS sub_account_sum,
a.balance - (sa_acc(a.id)) AS diff
FROM accounts a
INNER JOIN sub_account sa ON sa.account_id = a.id
WHERE a.balance != (sa_acc(a.id))
AND a.balance - (sa_acc(a.id)) < 5000
AND a.balance - (sa_acc(a.id)) >-5000
AND (
SELECT
COUNT(*)
FROM
sub_account sa
WHERE
sa.account_id = a.id
) > 1
答案 3 :(得分:0)
With sum_addi as
(select sa.account_id , sum(amount) as summ from sub_account sa
having count(*) > 1
and sum(amount) < 5000
and sum(amount) > -5000)
select
a.id,
a.balance as main_balance,
b.summ as sub_account_sum,
a.balance - b.summ as diff
from accounts a
inner join sum_addi b on a.account_id = b.id
where balance <> b.summ;