5

我有两个表 A 和 B 喜欢: A (id, dep_id)B (id, amount)

这些表中的数据是这样的

A                 B

id  dep_id        id   amount
--- -------       ---- --------
1   2             1    100    
2   3             2    200
3   NULL          3    300   
4   NULL          4    400

表 A 中的id列适用于id表 B。对于id表 A 中的给定值,可能存在表 B 中的 a 。dep_idid

要求是计算 B 中的条目及其所有相关条目的数量之和。这必须在一个 sql 查询中完成。我不能为此使用 PL/SQL 块。任何想法如何做到这一点。

例子:

sum(id=1) = 100(id=1,dep_id=2) + 200(id=2,dep_id=3) + 300(id=3) = 600
4

5 回答 5

5

您可以使用CONNECT BY ROOT构建依赖关系的链接(分层查询),然后聚合:

SQL> SELECT ID, SUM(amount)
  2    FROM (SELECT connect_by_root(a.id) ID, b.amount
  3            FROM a
  4            JOIN b ON a.id = b.id
  5           START WITH a.ID = 1
  6           CONNECT BY PRIOR a.dep_id = a.ID)
  7   GROUP BY ID;

        ID SUM(AMOUNT)
---------- -----------
         1         600

在 plsqlchallenge 上的这个 SQL 测验中,其他解决方案可用于类似但稍微复杂一点的模式(例如id:1需要 4x id:2id:3每个需要 8x)。

于 2013-05-14T14:23:21.247 回答
3

作为文森特查询的替代方法,您可以使用:

select sum(b.amount) 
from B b 
where b.id in (
    select a.id from A a start with a.id = 1 connect by a.id = prior a.dep_id
);

SQLFiddle:http ://sqlfiddle.com/#!4/d7d1c/5

于 2013-05-14T14:29:54.243 回答
2

另一种选择,使用递归 CTE:

with recur (id, dep_id, amount)as
(
  select A.id, A.dep_id, b.amount
  from A
  inner join B on A.id = b.id

  union all

  select recur.id, a.dep_id, b.amount
  from recur
  inner join A on recur.dep_id = a.id
  inner join B on a.id = b.id      
)
select id, sum(amount) 
from recur
group by id

在这里查看工作小提琴:http ://sqlfiddle.com/#!4/c1c83/2

于 2013-05-14T14:37:29.940 回答
0

我们可以使用递归查询来做到这一点。我无权访问数据库,但这是粗略的想法。查询结果可能不准确,这是在 DB2 中,

With Ax as
(
SELECT ID, DEP_ID FROM A
UNION ALL
SELECT AX.ID, A.DEP_ID
FROM AX, A
WHERE AX.DEP_ID = A.ID
)

SELECT A.ID, SUM(AMOUNT)
FROM AX AS A JOIN B
ON A.ID = B.ID

1 的结果集在 AX 中可能看起来像,

1 2
2 3
1 NULL
2 3
3 NULL
4 NULL
于 2013-05-14T14:34:51.380 回答
0

这是一个方法 - 很酷的技巧(来自具有不同名称的模式 - 你必须调整)

select part_id,  new_rec.quantity*sum(math_calc( math,2)) m, unit_of_measure
from ( SELECT rownum, level lvl, part_id, quantity, unit_of_measure
            , connect_by_isleaf || sys_connect_by_path(quantity,'*') math
from assembly
start with parent_part_id = new_rec.part_id
connect by parent_part_id = prior part_id ) p
group by part_id, unit_of_measure 

基本上 - 这部分

connect_by_isleaf || sys_connect_by_path(quantity,'*') math

将求和的数学方程式作为字符串 - 然后由这部分解析和计算

new_rec.quantity*sum(math_calc( math,2)) m
于 2013-05-14T15:03:08.687 回答