对具有相同值的“不同”行进行求和

时间:2017-01-04 14:06:51

标签: sql

我有一个数据库,它有一个可能有几个分配器的馈线,每个分配器可能有几个变压器,每个变压器可能有几个客户端和一定的kVA(电源到达客户端)。 我有以下代码:

SELECT f.feeder,
    d.distributor,
    count(DISTINCT t.transformer) AS total_transformers,
    sum(t.Kvan) AS Total_KVA,
    count(c.client) AS Clients,
FROM feeders f
    LEFT JOIN distributors d
        ON (d.feeder = f.feeder)
    LEFT JOIN transformers t
        ON (t.transformer = d.transformer)
    LEFT JOIN clients c
        ON (c.transformer = t.transformer)
WHERE d.transformer IS NOT NULL
GROUP BY f.feeder,
    d.distributor,
    f.feeder
ORDER BY f.feeder,
    d.distributor

总和应该带来变压器所具有的不同kVA的总和。每个变压器都有一定的kVA。问题是,1个变压器对于它已连接的所有客户端都有1kVA,但它会将其总和为每个客户端1kVA。 我需要将它分组到馈线和分配器上(我想知道分销商有多少kVA以及总共有多少客户)。 那么应该是什么“feeder1 | dist1 | 2 | 600 | 374”给我带来“feeder1 | dist1 | 2 | 130000 | 374”(1变压器有200 kVA而另一个有400,但它会将这两个374次相加而不是400 200)

1 个答案:

答案 0 :(得分:0)

您的数据模型看起来有点混乱,因为您已指定分销商可以拥有多个变压器(并且逻辑表明变压器仅在单个分销商处)但您的查询意味着变压器ID在分销商记录上,这通常意味着相反的关系...

因此,如果这是正确的,那么它必须意味着您在同一分销商的分销商表中有多个记录 - 即分销商不能成为分销商表中的唯一密钥,这使得查询很难准确地解释。 (例如,如果经销商的记录并非都有相同的支线ID,会发生什么?我猜你不会那么想答案......大概你的意思是不可能的,但是如果模型就像描述的那样并非不可能。更糟糕的是,我现在正在猜测其他表上的明显键是否实际上是唯一的...但我离题了...)

或许还有别的东西被打破了。 Point是您提供的信息可能不一致或不完整。由于我推断出一个异常的数据模型,我无法保证以下内容是无错误的(尽管如果你提供更多细节以便我可以做出更少的猜测,我可以改进答案)......

所以你知道麻烦的是,当你准备进行聚合时,变换器数据被嵌入一个不仅仅基于变换器身份的更大的行。有几种方法可以解决它,基本上都集中在改变你看待值聚合的方式。这是一个选项:

select f.feeder
     , dtc.distributor
       -- next values work because transformer is already unique per group
     , count(dtc.transformer) total_transformers
     , sum(dtc.kvam) total_kvam
     , sum(dtc.clients) clients
  from      feeder f
       join (select d.distributor
                  , d.feeder
                  , t.transformer
                  , max(t.kvan) as kvan   -- or min, doesn't matter
                  , count(distinct c.client) clients
               from           distributors d
                    left join transformers t
                           on d.transformer = t.transformer
                    left join clients c
                           on c.transformer = t.transformer
              where d.transformer is not null
              group by d.distributor, d.feeder, t.transformer
            ) dtc
         on dtc.feeder = f.feeder
 group by f.feeder, dtc.distributor

一些注意事项:

我将外部查询连接更改为内部连接,因为来自feeder的原始左连接的任何空行都将被原始的where子句消除。

无论如何,我保留了where子句;它与distributor - 到 - transformer左边连接一起有点奇怪,但与内连接或外连接不同,没有where子句(因为where子句作用于左表)值)。我正在避免从原始查询中更改语义,但这很奇怪,这可能是您想要再看一下的。

这里使用子查询的是,内部查询每个馈线/分配器/变换器返回一行 - 即对于每个馈线/分配器,它每个变换器返回一行。该行本身就是一个聚合,因此我们可以计算客户端,但由于该聚合中的所有行都来自同一个转换器记录,因此我们可以使用max()将该单个记录的kvan值放到聚合上。 / p>