使用许多值列透视数据表c#

时间:2016-03-10 18:12:59

标签: c# dynamic pivot

我发现了link

这里的代码可以使用数据透视值和数据透视表来旋转数据表。我需要的是根据日期进行调整,并保留所有其他值列,如下所示:

Date Column1 Column2 Column3
2010   10      20      30
2011   40      50      60

在这里,我将列名称作为第一行及其在年份下的值:

          2010  2011 
Column1    10    40
Column2    20    50
Column3    30    60

这是我现在的代码:

DataTable Pivot(DataTable dt, DataColumn pivotColumn, DataColumn pivotValue) {
    // find primary key columns 
    //(i.e. everything but pivot column and pivot value)
    DataTable temp = dt.Copy();
    temp.Columns.Remove( pivotColumn.ColumnName );
    temp.Columns.Remove( pivotValue.ColumnName );
    string[] pkColumnNames = temp.Columns.Cast<DataColumn>()
        .Select( c => c.ColumnName )
        .ToArray();

    // prep results table
    DataTable result = temp.DefaultView.ToTable(true, pkColumnNames).Copy();
    result.PrimaryKey = result.Columns.Cast<DataColumn>().ToArray();
    dt.AsEnumerable()
        .Select(r => r[pivotColumn.ColumnName].ToString())
        .Distinct().ToList()
        .ForEach (c => result.Columns.Add(c, pivotColumn.DataType));

    // load it
    foreach( DataRow row in dt.Rows ) {
        // find row to update
        DataRow aggRow = result.Rows.Find(
            pkColumnNames
                .Select( c => row[c] )
                .ToArray() );
        // the aggregate used here is LATEST 
        // adjust the next line if you want (SUM, MAX, etc...)
        aggRow[row[pivotColumn.ColumnName].ToString()] = row[pivotValue.ColumnName];
    }

    return result;
}

如何使用多个列值实现此结果?

1 个答案:

答案 0 :(得分:1)

我认为你需要采取略微不同的方法,因为你的方式略有不同。这是一种仅使用表格和pivotColumnName的方法。使用输入表计算出其他所有内容。

DataTable Pivot(DataTable table, string pivotColumnName)
{
    // TODO make sure the table contains at least two columns

     // get the data type of the first value column
    var dataType = table.Columns[1].DataType;

    // create a pivoted table, and add the first column
    var pivotedTable = new DataTable();
    pivotedTable.Columns.Add("Row Name", typeof(string));

    // determine the names of the remaining columns of the pivoted table
    var additionalColumnNames = table
        .AsEnumerable()
        .Select(x => x[pivotColumnName].ToString());

    // add the remaining columns to the pivoted table
    foreach (var columnName in additionalColumnNames)
        pivotedTable.Columns.Add(columnName, dataType);

    // determine the row names for the pivoted table
    var rowNames = table.Columns
        .Cast<DataColumn>()
        .Select(x => x.ColumnName)
        .Where(x => x != pivotColumnName);

    // fill in the pivoted data
    foreach (var rowName in rowNames)
    {
        // get the value data from the appropriate column of the input table
        var pivotedData = table
            .AsEnumerable()
            .Select(x => x[rowName]);

        // make the rowName the first value
        var data = new object[] { rowName }
            .Concat(pivotedData)
            .ToArray();

        // add the row
        pivotedTable.Rows.Add(data);
    }

    return pivotedTable;
}

以下是我用来测试的内容:

var dateColumn = new DataColumn("Date", typeof(int));
var column1 = new DataColumn("Column1", typeof(int));
var column2 = new DataColumn("Column2", typeof(int));
var column3 = new DataColumn("Column3", typeof(int));
var table = new DataTable();
table.Columns.Add(dateColumn);
table.Columns.Add(column1);
table.Columns.Add(column2);
table.Columns.Add(column3);
table.Rows.Add(new object[] { 2010, 10, 20, 30 });
table.Rows.Add(new object[] { 2011, 40, 50, 60 });
var pivotedTable = Pivot(table, "Date");