首页 文章

数据表中不连续的每小时数据,可能插入缺少的小时日期时间值和数据值为空?

提问于
浏览
0

我使用以下存储过程从SQL Server检索数据:

SELECT *
 FROM (
  SELECT CAST(DateTimeUTC as SmallDateTime) as [DateTime], DataValue, VariableID
  FROM DataValues
  WHERE SiteID = @siteID and VariableID = 1
 ) TableDate
PIVOT (SUM(DataValue) FOR VariableID IN ([1])) PivotTable ORDER BY [DateTime]

然后我用这些值填充DataSet DataTable:

DataSet myDataSet = new DataSet();
mySqlDataAdapter.Fill(myDataSet);
DataTable precip = myDataSet.Tables["Table"];
if (precip.Rows.Count > 0)
 {
  msPrec = precip.Rows[0].Field<DateTime>("DateTime");
  sPrec = string.Join<object>(", ",
   from r in precip.Rows.OfType<DataRow>() select r[1]);
 }
else
 {
  msPrec = DateTime.MinValue;
  sPrec = "";
 }

在上面的示例中,msPrec只是数据集开头的单个值 .

The problem is that I didn't consider that the hourly data may not be continuous.
这意味着可能存在数据库中未存储为NULL的丢失数据 . 所以一个DB记录完全有可能来自2013-04-26 04:00:00,而DB中的下一个记录是从2013-04-26 08:00:00到05:00,06:00, 07:00失踪 .

也可能缺少多天的数据,而不是在同一天内的几个小时 .

我正在使用HighCharts的HighStock绘制这些数据,非常类似于此示例中所示:http://www.highcharts.com/stock/demo/data-grouping除了它们在示例中预处理数据以包含缺失数据的NULL值,您可以通过绘图中的数据间隙看到 .

解决这个问题的伪代码对我来说很清楚:

  • 循环存储过程的输出
  • 将当前记录DateTime与下一个记录DateTime进行比较
  • 如果nextRecordDateTime = currentRecordDateTime 1小时,则继续下一条记录
  • 如果nextRecordDateTime!= currentRecordDateTime 1小时,那么
    以小时计算currentRecordDateTime和nextRecordDateTime之间的差异
    将每个缺失小时的DateTime和DataValue(NULL)插入DataTable
  • 在最后插入的记录中继续循环

我查看了MSDN上的DataTable Class,但没有看到任何看似相关的内容 . DataRow Class会让我遍历行,但我不知道如何在当前行中获取下一行的值 .

所以我有两个问题;

如何在DataSet DataTable的当前记录(行)上考虑下一条记录(行)的DateTime值?

如何在正确的位置将数据插入DataSet DataTable,而不是将其添加到DataTable的末尾?或者解决方案是将它添加到最后并对表进行排序?

2 回答

  • 1

    我写了一段代码,它采用DataTable沉淀并插入缺少小时值的新行 . 当表的第一列具有值05:00,07:00,10:00时;经过以下操作,输出将分别为05:00,06:00,07:00,08:00,09:00,10:00 .

    我希望这就是你要找的东西:

    DataRow row;
            DateTime curRowDt, nextRowDt;
            object curObj, nextObj; // Used only for conversions
    
            for (int i = 0; i < precip.Rows.Count - 1; ++i)
            {
                // Resetting id numbers
                precip.Rows[i][2] = i;
    
                // Throws exception when changed to
                // curRowDt = (DateTime)precip.Rows[i][0];
                curObj = precip.Rows[i][0];
                nextObj = precip.Rows[i + 1][0];
                curRowDt = Convert.ToDateTime(curObj);
                nextRowDt = Convert.ToDateTime(nextObj);
    
                if (curRowDt.AddHours(1.0) != nextRowDt)
                {
                    for (int j = 1; j < nextRowDt.Subtract(curRowDt).Hours; ++j)
                    {
                        ++i;
                        row = precip.NewRow();
                        row.ItemArray = new object[] { curRowDt.AddHours(j), null, i };
                        precip.Rows.InsertAt(row, i);
                    }
                }
            }
            // Resetting last row's id number
            precip.Rows[precip.Rows.Count - 1][2] = precip.Rows.Count - 1;
    
  • 0

    为了完整起见,只是发布这个,这是Mert Erol在接受的答案中提出的调整后的代码 . 我认为,是否需要身份证号码存在误传 . 他们不是 .

    DataTable DataRows包含ItemArray,其中第一列是DateTime,第二列是DataValue .

    这是Merl的代码包含在我现在使用的函数中 . 再次感谢Mert,如果可以的话,我会给你一些更多的赞成!

    EDIT: UPDATED 用于正确处理多天丢失数据的情况 . 使用 TimeSpan 似乎最适合获得数据点之间的准确小时数 .

    public DataTable fillMissingHours(DataTable currentDataTable)
    {
        // iterates through the current DataTable to find missing data and fill it in with
        // the correct DateTime and NULL DataValue
        DataRow row;
        DateTime curRowDt, nextRowDt;
        object curObj, nextObj; // Used only for conversions
    
        for (int i = 0; i < currentDataTable.Rows.Count - 1; ++i)
        {
            curObj = currentDataTable.Rows[i][0];
            nextObj = currentDataTable.Rows[i + 1][0];
            curRowDt = Convert.ToDateTime(curObj);
            nextRowDt = Convert.ToDateTime(nextObj);
    
            if (curRowDt.AddHours(1.0) != nextRowDt)
            {
                TimeSpan deltaTime = nextRowDt - curRowDt;
                for (int j = 1; j < deltaTime.TotalHours; ++j)
                {
                    ++i;
                    row = currentDataTable.NewRow();
                    row.ItemArray = new object[] { curRowDt.AddHours(j), null };
                    currentDataTable.Rows.InsertAt(row, i);
                }
            }
        }
    
        return currentDataTable;
    }
    

相关问题