在 SQL 语句中查找递归和

Posted

技术标签:

【中文标题】在 SQL 语句中查找递归和【英文标题】:Finding recursive sum in SQL statement 【发布时间】:2013-05-08 20:51:30 【问题描述】:

我有两个表 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 列包含表 B 的 id。对于表 A 中的给定 id,可能有一个 dep_id 包含表 B 的 id

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

例子:

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

【问题讨论】:

有点困惑。这是等级制度吗? (id = 孩子,dep_id = 父母)?还是我需要更多的咖啡? 您需要一个支持WITH RECURSIVE 的数据库版本才能在一个查询中获得此信息。您可以使用吗? @AndrewLazarus 分层查询自 Oracle 2 以来一直存在(我相信是 1978 年 :) @VincentMalgrat:我自己使用 Postgres,所以不太了解 Oracle 的增强。无论如何,这是这种查询的必经之路。 Help calculating complex sum in hierarchical dataset 的可能重复项 【参考方案1】:

你可以使用CONNECT BY ROOT建立一个依赖链接(hierarchical query),然后聚合:

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

其他解决方案可用于this SQL quiz on plsqlchallenge 上类似但稍微复杂一点的架构(例如id:1 需要 4xid:2,每个需要 8xid:3)。

【讨论】:

【参考方案2】:

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

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

【讨论】:

【参考方案3】:

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

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

【讨论】:

【参考方案4】:

另一种选择,使用递归 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

【讨论】:

【参考方案5】:

我们可以使用递归查询来做到这一点。我无权访问数据库,但这是粗略的想法。查询结果可能不准确,这是在 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

【讨论】:

以上是关于在 SQL 语句中查找递归和的主要内容,如果未能解决你的问题,请参考以下文章

SQL 语句递归查询 With AS 查找所有子节点

mysql递归查询语句

sql用啥方法可以实现递归函数?

SQL 递归查询,意淫CTE递归的执行步骤

递归SQL语句

递归 Cte 在 SQL 中查找 Min 和 Max 相关数据? [关闭]