SQL解决方案,可根据增量值实时计算聚合消耗

时间:2019-02-27 12:06:34

标签: sql sql-server-2012 common-table-expression database-trigger sql-view

我有一个SQL表,其中列每秒具有增量值。 我如何确定一个小时的变化或消费价值?

For e.g.
Date            Time                EnergyKWH
2019-02-16      18:00:00.000        43.366
2019-02-16      18:00:01.000        43.367
2019-02-16      18:00:02.000        43.369
.................
............
.........
2019-02-16      19:00:00.000        70.886

(每1秒1条记录,每1小时3600条)

我如何才能找到从18:00到19:00的每小时总消耗量,并分别计算所有24小时的消耗量? (每小时消耗量将是18:00和19:00之间的差值。

Expected Result :
Date            StartTime           EndTime             EnergyKWH
2019-02-16      18:00:00            19:00:00            27.250        (Difference of 70.886-43.366)
2019-02-16      19:00:00            20:00:00            21.561        (Next Value Approximation)

数据每秒都在传输中,我需要一个可以自动执行此过程的解决方案。

  

我应该考虑使用诸如View或CTE之类的工具进行即时计算,还是使用触发器将计算结果发送到另一张保存我所需结果集的表中?

请记住,这将是所有日期和所有24小时的连续过程。理想情况下,我希望至少保留7天的计算/结果数据。我的数据库版本是MS SQL 2012。

我只需要今天和过去任何一天的18:00和19:00,以及所有24小时的值的差异。

  

我可以很容易地用数学方法进行计算,但是随着新数据的不断流入,什么是使该过程自动化的最佳方法呢?

2 个答案:

答案 0 :(得分:0)

如果所有数据都没有间隙,则类似以下内容:

private static void ReplaceRolesAndMembersWithInitialValues(Database db, Model model, List<CubeRoleModel> initRolesForPostgres)
    {
        var roles = model.Roles;
        if (roles.Count > 0)
        {
            var rolesName = roles.Select(x => x.Name).Distinct().ToList();
            foreach (var n in rolesName)
            {
                roles.Remove(n);
            }
            model.SaveChanges();
        }

        if (initRolesForPostgres.Count > 0)
        {
            var tablesNames = new HashSet<string>(model.Tables.Select(a => a.Name).Distinct().ToList());
            var tables = model.Tables;
            Dictionary<string, Table> dictTables = new Dictionary<string, Table>();
            foreach (var t in tables)
            {
                dictTables.Add(t.Name, t);
            }

            foreach (var n in initRolesForPostgres)
            {
                ModelRole newRole = new ModelRole
                {
                    Name = n.RoleName,
                    Description = n.RoleDescription,
                    ModelPermission = n.ModelPermission
                };

                if (n.Members.Count > 0)
                {
                    foreach (var m in n.Members)
                    {
                        var nMem = new WindowsModelRoleMember
                        {
                            MemberName = m.MemberName
                        };
                        newRole.Members.Add(nMem);
                    }
                }

                if (n.TablePermissions.Count > 0)
                {
                    var tb = newRole.TablePermissions;
                    foreach (var tabPerm in n.TablePermissions)
                    {
                        if (tables.Contains(tabPerm.TableName) && string.IsNullOrWhiteSpace(tabPerm.TableFilters) == false)
                        {
                            TablePermission newTablePer = new TablePermission
                            {
                                Name = tabPerm.TableName,
                                FilterExpression = tabPerm.TableFilters
                            };

                            if (newTablePer.Validate().ContainsErrors) { continue; }
                            tb.Add(newTablePer);
                        }
                    }
                }

                if (newRole.Validate().ContainsErrors) { continue; }
                model.Roles.Add(newRole);
            }
            model.SaveChanges();
        }
    }

这使用ISO / ANSI标准功能。这些可能因数据库而异,但是想法是相同的。

在SQL Server中,它表示为:

select t.date, t.time as starttime,
       lead(t.time) over (order by t.date, t.time) as endtime,
       (lead(EnergyKWH) over (order by t.date, t.time) -
        EnergyKWH
       ) as EnergyKWH_diff
from t
where extract(minute from time) = 0
order by t.date, t.time;

答案 1 :(得分:0)

好的,所以我有一个可能的解决方案,但是我不想这样做,因为它非常粗糙而且非常慢。

它需要5秒钟以上才能获取7天的数据,随着数据的扩展,这种情况将继续增加。

创建视图或CTE是否有助于提高性能? 我知道我可以在视图中添加一个额外的索引,但是CTE更好,因为我递归地击中了表(自连接将替换此嵌套查询)

示例解决方案查询:

SELECT 
    (CASE WHEN ((DATEPART(Minute,p.[Time])) = 0 AND (DATEPART(SECOND,p.Time)) = 0)
                AND (DateAdd(HOUR,1, p.[Time])  IS NOT NULL)
        THEN 
             (Select -1 * (p.EnergyKWH - (Select EnergyKWH from FactPLCDetails p2 WHERE p2.[Time] = (DateAdd(HOUR,1, p.[Time])) AND p.[Date] = p2.[Date]) ))
        END
    )
    as [EnergyDiff],
    p.[Time] As Start_Time,
    (DateAdd(HOUR,1, p.[Time])) as End_Time,
    p.[Date]     
from FactPLCDetails p
ORDER BY [EnergyDiff] DESC