【问题标题】:Arbitrary heirachy node summation in Oracle SQLOracle SQL 中的任意层次节点求和
【发布时间】:2014-03-20 16:24:42
【问题描述】:

我正在创建一个数据库来总结通过各种总线连接的电气负载系统。这个想法是能够检查没有总线超过其额定负载。我正在使用 APEX 和 Oracle 数据库。

我有两张桌子,LOADBUS

LOAD 具有列 IDENTIFIER, PARENT_BUS, POWER

BUS 具有列 IDENTIFIER, PARENT_BUS

(这只是表格的简化,但其他数据与这个问题无关我不认为)

我创建了一个看起来有点像这样的表结构:

BUS 0 (root bus)
  BUS 1
   -LOAD 1000
   -LOAD 1009
   BUS 101
     -LOAD 1001
     -LOAD 1002
     -LOAD 1007
   BUS 102
     -LOAD 1003
  BUS 2
   BUS 201
     -LOAD 1004
     -LOAD 1008
   BUS 202
     -LOAD 1005
     -LOAD 1006

有一组总线使用从BUS.PARENT_BUSBUS.IDENTIFIER 的外键链接到总线表中的另一总线。负载表中的负载也通过外键链接到总线:即LOAD.PARENT_BUSBUS.IDENTIFIER。通常会有数百甚至数千个负载连接到几十个总线。

注意负载可以连接到总线结构中的任何位置,并且可以有任何级别的总线(尽管我在示例中只显示了两个级别 - 三个或更多级别会不常见但并非不可能)

我需要对每个总线级别的所有负载求和,并将其馈送到下一个更高的总线。即对于BUS 101,我需要LOAD 1001 + LOAD 1002 + LOAD 1007 的总和,然后对于BUS 1,我需要BUS 101 + BUS 102 + LOAD 1000 + LOAD 1009 的总和。

我试过这样做:

SELECT bus.IDENTIFIER AS "PARENT", bus.PARENT_BUS AS "GRANDPARENT", SUM(load.POWER) AS "POWER", level
FROM BUS_DATA bus
LEFT JOIN LOAD_DATA load
ON load.PARENT_BUS = bus.IDENTIFIER
START WITH bus.PARENT_BUS = '0' -- This is the root that all buses eventually link to
CONNECT BY PRIOR bus.IDENTIFIER = bus.PARENT_BUS
GROUP BY bus.IDENTIFIER, bus.PARENT_BUS, level;

这给了我

PARENT, GRANDPARENT, POWER, LEVEL
201     2            307.6  2
202     2            189.4  2

这是正确的,因为使用我用来生成它的数据没有负载附加到 BUS 2。我还需要查看一行:

PARENT, GRANDPARENT, POWER, LEVEL
2       0            497    1

即201 和 202 的总和,加上可能直接连接到 BUS 2 的任何负载。

如何使总功率数据通过总线结构馈送到父总线?

【问题讨论】:

  • 您可以发布示例创建表和插入以及您需要查看的确切结果吗?还有你使用的是什么 Oracle 版本?

标签: sql oracle join sum


【解决方案1】:

您的部分问题是您已经将总线的层次结构实现为邻接列表,它给出了您正在尝试做的事情以及我假设的是数据的性质(总线是相对静态的,负载是相对动态的) 不是最简单或最有效的方法。

查看this 问题,了解表示数据的各种方法。请查看问题中的第二个链接以帮助您入门。

即兴发挥,我建议您实现路径枚举存储方法,因为它似乎几乎是总线 ID 中固有的。

【讨论】:

  • 嗯,也许我说其他列不相关的地方不太正确。 BUS 和 LOAD 表都有一个 Circuit Breaker 列,它是 BREAKER 表的外键,然后包含有关断路器的信息。我无法摆脱 BUS 表,这肯定会让事情变得更容易。使用路径枚举方法可以更有效地查找父母和孩子,但我仍然需要 LOAD 和 BUS 表,并且我仍然需要一种方法来递归地对附加到每条总线的负载求和。我看不出路径枚举格式对此有何帮助。
  • 当然可以,如果您的总线的主键类似于 1, 1/101, 1/101/1001, 1/101/1002 那么查询类似于 SELECT SUM(Load.Power) FROM BUS INNER JOIN LOAD ON BUS.ID=LOAD.BUS WHERE BUS.ID LIKE '1*' 将起作用 - 您实际上不会这样做,SQL SERVER 对这种类型的 HeirachicalID(称为 HeirachicalID)具有本机数据类型支持,我相信甲骨文也是。
  • 好的,谢谢。这确实有点道理。 :P 我会看看甲骨文是否有这种分层类型。我担心我必须做很多字符串操作才能让它工作,但也许不会。
  • Oracle 显然没有这个 HeirachicalID。它似乎是 SQL Server 独有的。所以在 Oracle 中做这种存储需要大量的字符串操作。
  • 你可以使用整数而不是字符串;您的最低级别总线是单位和 10,下一级是 100 和 1000,依此类推 - 因此,每条总线都在其 id 中承载其整个路径。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-05-31
  • 1970-01-01
  • 1970-01-01
  • 2019-07-27
  • 2011-10-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多