繁体   English   中英

基于多个日期范围的值的聚合总和 - SQL Server

[英]Aggregate Sum of values based on multiple date ranges - SQL Server

我正在尝试根据建筑项目生命周期中的面板状态及时确定向电源面板添加额外负载的效果。 配电盘可以有许多与其相关的负载(最多 240 个),并且可以在任何给定时间根据施工进度安装或卸载这些负载。 面板上的负载总和在项目的生命周期中波动。 仅仅因为今天的负载为 90%,并不自动意味着您有 10% 可用,因为可以安排明天安装新负载。 必须始终考虑项目生命周期。

我需要一个查询,根据面板上所有负载的安装/卸载日期确定给定日期面板的最大负载。

以下是负载及其安装/卸载日期的示例视图。

CREATE TABLE #temp(
   PanelID     INTEGER  NOT NULL 
  ,LOADID      INTEGER  NOT NULL
  ,Load        VARCHAR(7) NOT NULL
  ,kVA         NUMERIC(5,2) NOT NULL
  ,InstallDate DATE  NOT NULL
  ,DemoDate    DATE 
);
INSERT INTO #temp(PanelID,LOADID,Load,kVA,InstallDate,DemoDate) VALUES (1380,46706,'AUTO26',43.95,'07/07/1905','27/10/2016');
INSERT INTO #temp(PanelID,LOADID,Load,kVA,InstallDate,DemoDate) VALUES (1380,46706,'AUTO26',43.95,'07/07/1905','27/10/2016');
INSERT INTO #temp(PanelID,LOADID,Load,kVA,InstallDate,DemoDate) VALUES (1380,15539,'AUTO22',43.95,'01/01/2015',NULL);
INSERT INTO #temp(PanelID,LOADID,Load,kVA,InstallDate,DemoDate) VALUES (1380,20188,'OVEN101',46.47,'29/06/2017',NULL);
INSERT INTO #temp(PanelID,LOADID,Load,kVA,InstallDate,DemoDate) VALUES (1380,20186,'OVEN101',63.05,'29/06/2017',NULL);
INSERT INTO #temp(PanelID,LOADID,Load,kVA,InstallDate,DemoDate) VALUES (1380,46705,'AUTO28',61.25,'07/07/1905','27/10/2016');
INSERT INTO #temp(PanelID,LOADID,Load,kVA,InstallDate,DemoDate) VALUES (1380,20186,'OVEN101',63.05,'29/06/2017',NULL);
INSERT INTO #temp(PanelID,LOADID,Load,kVA,InstallDate,DemoDate) VALUES (1380,46705,'AUTO28',61.25,'07/07/1905','27/10/2016');
INSERT INTO #temp(PanelID,LOADID,Load,kVA,InstallDate,DemoDate) VALUES (1380,15539,'AUTO22',43.95,'01/01/2015',NULL);
INSERT INTO #temp(PanelID,LOADID,Load,kVA,InstallDate,DemoDate) VALUES (1380,20188,'OVEN101',46.47,'29/06/2017',NULL);
INSERT INTO #temp(PanelID,LOADID,Load,kVA,InstallDate,DemoDate) VALUES (1380,15538,'AUTO22',66.65,'01/01/2015',NULL);
INSERT INTO #temp(PanelID,LOADID,Load,kVA,InstallDate,DemoDate) VALUES (1380,20187,'OVEN101',50.44,'29/06/2017',NULL);
INSERT INTO #temp(PanelID,LOADID,Load,kVA,InstallDate,DemoDate) VALUES (1380,46704,'AUTO26',61.25,'07/07/1905','27/10/2016');
INSERT INTO #temp(PanelID,LOADID,Load,kVA,InstallDate,DemoDate) VALUES (1380,46707,'AUTO28',43.95,'07/07/1905','27/09/2016');
INSERT INTO #temp(PanelID,LOADID,Load,kVA,InstallDate,DemoDate) VALUES (1380,15538,'AUTO22',66.65,'01/01/2015',NULL);
INSERT INTO #temp(PanelID,LOADID,Load,kVA,InstallDate,DemoDate) VALUES (1380,20187,'OVEN101',50.44,'29/06/2017',NULL);
INSERT INTO #temp(PanelID,LOADID,Load,kVA,InstallDate,DemoDate) VALUES (1380,46704,'AUTO26',61.25,'07/07/1905','27/10/2016');
INSERT INTO #temp(PanelID,LOADID,Load,kVA,InstallDate,DemoDate) VALUES (1380,46707,'AUTO28',43.95,'07/07/1905','27/09/2016');

迄今为止,我的解决方案是使用光标查找与面板上的负载相关的每个给定日期的面板负载(总和或 kVA)。 由于面板上最多可以有 240 个负载,这会对性能造成重大影响。

有没有更好的方法来做到这一点?

编辑:我已按照建议简化了创建表。 您只需按面板分组并对 kVA 列求和即可检索结果。 但是,我希望它基于面板上每个负载的安装日期。 如果卸载日期小于安装日期,则不应出现在聚合函数中。

我假设 DemoDate 是从板上移除负载的日期,而 null 表示它们没有被移除。 这是一个公共表表达式查询,它应该给出持续时间内的最大 kVA:

SET DATEFORMAT dmy;

CREATE TABLE #temp(
     SourceID       INTEGER        NOT NULL
    ,PanelID        INTEGER        NOT NULL
    ,BP_DP          INTEGER        NOT NULL
    ,depth          BIT            NOT NULL
    ,LOADID         INTEGER        NOT NULL
    ,Load           VARCHAR(7)     NOT NULL
    ,kVA            NUMERIC(5,2)   NOT NULL
    ,InstallDate    DATE           NOT NULL
    ,DemoDate       DATE
);

INSERT INTO #temp
    (SourceID, PanelID, BP_DP, depth, LOADID, Load,      kVA,   InstallDate,  DemoDate    )
VALUES
    (1375,     1380,    2,     1,     46706,  'AUTO26',  43.95, '07/07/1905', '27/10/2016'),
    (1380,     1380,    2,     0,     46706,  'AUTO26',  43.95, '07/07/1905', '27/10/2016'),
    (1375,     1380,    2,     1,     15539,  'AUTO22',  43.95, '01/01/2015', NULL        ),
    (1375,     1380,    2,     1,     20188,  'OVEN101', 46.47, '29/06/2017', NULL        ),
    (1380,     1380,    2,     0,     20186,  'OVEN101', 63.05, '29/06/2017', NULL        ),
    (1380,     1380,    2,     0,     46705,  'AUTO28',  61.25, '07/07/1905', '27/10/2016'),
    (1375,     1380,    2,     1,     20186,  'OVEN101', 63.05, '29/06/2017', NULL        ),
    (1375,     1380,    2,     1,     46705,  'AUTO28',  61.25, '07/07/1905', '27/10/2016'),
    (1380,     1380,    2,     0,     15539,  'AUTO22',  43.95, '01/01/2015', NULL        ),
    (1380,     1380,    2,     0,     20188,  'OVEN101', 46.47, '29/06/2017', NULL        ),
    (1375,     1380,    2,     1,     15538,  'AUTO22',  66.65, '01/01/2015', NULL        ),
    (1375,     1380,    2,     1,     20187,  'OVEN101', 50.44, '29/06/2017', NULL        ),
    (1375,     1380,    2,     1,     46704,  'AUTO26',  61.25, '07/07/1905', '27/10/2016'),
    (1375,     1380,    2,     1,     46707,  'AUTO28',  43.95, '07/07/1905', '27/10/2016'),
    (1380,     1380,    2,     0,     15538,  'AUTO22',  66.65, '01/01/2015', NULL        ),
    (1380,     1380,    2,     0,     20187,  'OVEN101', 50.44, '29/06/2017', NULL        ),
    (1380,     1380,    2,     0,     46704,  'AUTO26',  61.25, '07/07/1905', '27/10/2016'),
    (1380,     1380,    2,     0,     46707,  'AUTO28',  43.95, '07/07/1905', '27/10/2016');   

WITH cte
AS
(
    SELECT 
        t1.PanelID,
        t1.InstallDate,
        SUM(t2.kVA) LoadAferInstall
    FROM
        (SELECT DISTINCT
            PanelID,
            InstallDate
        FROM
            #Temp
        ) t1
        JOIN #Temp t2
            ON t1.PanelID = t2.PanelID
            AND t2.InstallDate <= t1.InstallDate
            AND (t2.DemoDate IS NULL OR t2.DemoDate >= t1.InstallDate)
    GROUP BY
        t1.PanelID, t1.InstallDate
)
SELECT
    PanelID,
    MAX(LoadAferInstall) MaxPanelLoad_kVA
FROM
    cte
GROUP BY
    PanelID
;

DROP TABLE #temp

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM