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 只是数据集开头的单个值。

问题是我没有考虑每小时的数据可能不连续。
这意味着可能缺少未在数据库中存储为 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 类,但没有看到任何相关的内容。DataRow 类可以让我遍历行,但我不清楚如何在当前行中获取下一行的值。

所以我有两个问题;

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

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

4

2 回答 2

1

我编写了一段代码,它采用 DataTable precip 并插入缺少小时值的新行。当表格的第一列的值为 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;
于 2013-04-28T08:10:13.887 回答
0

为了完整起见,仅发布此内容,这是 Mert Erol 在接受的答案中提出的调整后的代码。我认为对于是否需要身份证号码存在误解。他们不是。

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

这是包装在我现在使用的函数中的 Merl 代码。再次感谢 Mert,如果可以的话,我会给你更多的支持!

编辑:更新正确处理数据丢失多天的情况。使用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;
}
于 2013-04-28T20:54:47.603 回答