如何以 .NET 数据表为中心

How to pivot on a .NET DataTable

我有以下格式的数据:

NodeName, ReadingDate, Value
NY, 5/10/2010, 5
NY, 5/11/2010, 7
TX, 5/10/2010, 8
TX, 5/11/2010, 9

...

我想将其旋转为:

ReadingDate, NY, TX
5/10/2010, 5, 8
5/11/2010, 7, 9

关键是节点名称的数量未知,所以我无法对它们进行硬编码。还有大约2000个日期和150个节点名称。

现在我制作了一个数据 table,我在其中对 ReadingDate 列进行了硬编码,然后在 NodeName 上使用不同的名称来获取唯一的名称值并使用它制作列。然后我进入并在所有 ReadingDates 上独一无二,并用它们做记录。所以现在我有了列和 ReadingDates。然后我进去并填写值。这可行,但您可以猜到它相当慢。我想知道是否有更简单快捷的方法来旋转我拥有的数据。

这是我目前的情况:

// get the data from the database
SqlDataReader rdr = cmd.ExecuteReader();

// load into a datatable for processing
DataTable tbl = new DataTable();
tbl.Load(rdr);

// add date column and a column for all NodeNames
DataTable pivotData1 = new DataTable();
pivotData1.Columns.Add("ReadingDate", typeof(DateTime));

DataView view = new DataView(tbl);
DataTable nodeNamesData = view.ToTable(true, "NodeName");
foreach (DataRow row in nodeNamesData.Rows)
{
    string data = row["NodeName"].ToString();
    DataColumn col = new DataColumn(data, typeof(double));
    col.DefaultValue = 0;
    pivotData1.Columns.Add(col);
}

// add all unique row labels
DataView dateView = new DataView(tbl);
DataTable dateData = dateView.ToTable(true, "ReadingDate");
foreach (DataRow row in dateData.Rows)
{
    DataRow newRow = pivotData1.NewRow();
    newRow["ReadingDate"] = row["ReadingDate"];

    pivotData1.Rows.Add(newRow);
}

// fill in the rest of the row data
foreach (DataRow row in pivotData1.Rows)
{
    var rowLabel = DateTime.Parse(row["ReadingDate"].ToString());

    // query to get all nodes for this date
    var qry = (from a in tbl.AsEnumerable()
               where a.Field<DateTime>("ReadingDate") == rowLabel
               select a);

    // loop over and fill in the column data for this date
    foreach (var r in qry)
    {
        double val = 0.0;

        if(r["Value"].ToString() != string.Empty)
            val = Convert.ToDouble(r["Value"].ToString());

        string col = r.Field<string>("NodeName");

        Console.WriteLine("Date = " + rowLabel + " Node = " + col + " Value = " + val);

        row.SetField<double>(col, val);
    }
}

第 1 步:获取所有节点名称的列表 (SELECT DISTINCT NodeName FROM myTable)。

第 2 步:将它们放在方括号中并创建一个逗号分隔的字符串:[NY], [TX], ....

第 3 步:使用此字符串构造一个 SQL Server PIVOT statement 其中 returns 所需的数据集。

注意:由于节点名称将成为您的 SQL 语句的一部分,因此请务必对它们进行 清理 以避免 SQL 注入。 (不幸的是,这里不能使用 SQL 参数,因为节点名称实际上变成了列名称。)