读取 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 部分之外,这将替换您的整个代码。
首先,我是第一次在这里提问,希望我的解释足够好。
我必须从数据库中读取 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 部分之外,这将替换您的整个代码。