如何在.NET DataTable上进行数据透视

时间:2015-10-22 17:03:25

标签: c# datatable pivot

我的数据格式为:

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个节点名称。

现在我创建一个数据表,我在其中对ReadingDate列进行硬编码,然后在NodeName上使用distinct来获取唯一的名称值并使用该列创建列。然后我进入并在所有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 个答案:

答案 0 :(得分:1)

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

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

步骤3:使用此字符串构造SQL Server PIVOT statement,返回所需的数据集。

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