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 として格納されていない欠落データがある可能性があることを意味します。したがって、1 つの 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 時間の場合、次のレコードに進みます
- if nextRecordDateTime != currentRecordDateTime + 1 時間、次に
  currentRecordDateTime と nextRecordDateTime の差を時間単位で計算
  します 不足している各時間の DateTime と DataValue (NULL) を DataTable に挿入します
- 最後に挿入されたレコードでループを続けます

MSDN でDataTable クラスを見ましたが、関連するものは何もありませんでした。DataRow クラスを使用すると、行をループ処理できますが、現在の行にいる間に次の行の値を取得する方法がわかりません。

2 つの質問があります。

DataSet DataTable の現在のレコード (行) で次のレコード (行) の DateTime 値を考慮するにはどうすればよいですか?

行を DataTable の末尾に追加するのではなく、DataSet DataTable の正しい位置に挿入するにはどうすればよいですか? それとも、最後に追加してテーブルをソートする解決策はありますか?

4

2 に答える 2

0

完全を期すためにこれを投稿するだけです。これは、受け入れられた回答で Mert Erol が思いついた調整済みのコードです。ID 番号が必要かどうかについて誤解があったと思います。ではない。

DataTable DataRows には、最初の列が DateTime で 2 番目の列が DataValue である ItemArray が含まれています。

これは、私が現在使用している関数にラップされた 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 に答える