读取 DataTable 并重新排列它,同时有效地更改时间戳列

Read DataTable and rearrange it while changing timestamp column efficiently

首先,我是第一次在这里提问,希望我的解释足够好。

我必须从数据库中读取 table 这种格式:

IdSignal 价值 年份 月份 小时 分钟 第二 毫秒
1 50.4 2021 06 21 13 25 34 751
2 71.0 2021 06 21 13 25 34 764
3 21.3 2021 06 21 13 25 34 783

并将其更改为 table,如下所示:

时间戳 1 2 3
2021/06/21 13:25:34.7 50.4 71.0 21.3

我开发了一个功能代码,但是太慢了(我已经能够减少执行时间,之前更糟,但现在我卡住了):

using (SqlConnection connection = new SqlConnection(connString))
            {
                connection.Open();
                SqlCommand command = new SqlCommand(queryString, connection);
                if ((int)connection.State == 1)
                {
                    MessageBox.Show("Connection opened!");
                }
                else
                {
                    MessageBox.Show("Something went wrong openning the connection! " + connection.State.ToString());
                }

                SqlDataAdapter da = new SqlDataAdapter(command);
                da.Fill(valueTable);
                foreach (DataRow row in valueTable.Rows)
                {
                    DateTime timestamp = new DateTime(row.Field<int>("Year"),
                        row.Field<int>("Month"),
                        row.Field<int>("Day"),
                        row.Field<int>("Hour"),
                        row.Field<int>("Minute"),
                        row.Field<int>("Second"),
                        row.Field<int>("Millisecond"));

                    string idSignal = row.Field<int>("IdSignal").ToString();
                    double value = row.Field<double>("Value");

                    try
                    {
                        if (finalTable.Select().Last().Field<String>("Timestamp") == timestamp.ToString("MM/dd/yyyy HH:mm:ss.f"))
                        {
                            finalTable.Select().Last()[idSignalNames[idSignal]] = value;
                        }
                        else
                        {
                            DataRow tempRow = finalTable.NewRow();

                            tempRow["Timestamp"] = timestamp.ToString("MM/dd/yyyy HH:mm:ss.f");

                            tempRow[idSignalNames[idSignal]] = value;
                            finalTable.Rows.Add(tempRow);
                        }
                    }
                    catch (Exception ex)
                    {
                        DataRow tempRow = finalTable.NewRow();

                        tempRow["Timestamp"] = timestamp.ToString("MM/dd/yyyy HH:mm:ss.f");

                        tempRow[idSignalNames[idSignal]] = value;
                        finalTable.Rows.Add(tempRow);
                        //System.Console.WriteLine("The first row has been added to finalTable");
                    }

现在,经过的时间是 3.5 秒

谢谢!

编辑 1

Can you describe in words what you are trying to achieve there? What is column 1,2 and 3 in that result table? – Tim Schmelter

第一个table,来自DB的那个,每个IdSignal都有一行,总共有9个IdSignal。 table 有超过 20k 行,对每个 IdSignal 重复测量,即 1,2,3,4,5,6,7,8,9,1,2,3,4 等。每组测量在秒的相同小数部分内,即 1 --> 13:25:34.7xx,2-->13:25:34.7xx,当它再次从 IdSignal 1 开始时,它位于 13:25:34 .8xx 等等。

我的目的是改变它,让每个信号(1、2、3 等)有一列,每个小数秒有一行。

抛开您可能能够更有效地在数据库中执行此操作的可能性,如果您想在内存中执行此操作,您可以使用以下方法优化可读性和性能:

var timeGroups = valueTable.AsEnumerable()
    .Select(GetRowInfo)
    .GroupBy(x => x.Time)
    .ToList();
            
DataTable finalTable = new DataTable();
finalTable.Columns.Add("Timestamp", typeof(DateTime));
int maxColumn = timeGroups.Max(g => g.Count());
for(int i = 1; i <= maxColumn; i++)
    finalTable.Columns.Add(i.ToString(), typeof(double));

foreach(var grp in timeGroups)
{
    DataRow addedRow = finalTable.Rows.Add();
    addedRow.SetField("Timestamp", grp.Key);
    int col = 0;
    foreach(var row in grp)
    {
        addedRow.SetField((++col).ToString(), row.Value);
    }
}

(DataRow Row, DateTime Time, string IdSignal, double Value) GetRowInfo(DataRow r)
{
    DateTime time = new DateTime(r.Field<int>("Year"), r.Field<int>("Month"), r.Field<int>("Day"), r.Field<int>("Hour"), r.Field<int>("Minute"), r.Field<int>("Second"), r.Field<int>("Millisecond"));
    string idSignal = r.Field<int>("IdSignal").ToString();
    double value = r.Field<double>("Value");
    return (r, time, idSignal, value);
}

除了填充源 table 的 Ado.Net 部分之外,这将替换您的整个代码。