【问题标题】:How do I transform a database table into a "pivot" DataTable?如何将数据库表转换为“数据透视”数据表?
【发布时间】:2015-07-21 08:13:08
【问题描述】:

我的数据看起来像这样,例如:

 | MemberID | Username | QuestionID |     Question     | Answer | 
 |----------|----------|------------|------------------|--------|
 |    58    |   John   |     1      | Recommend This?  |  Yes   |
 |    58    |   John   |     2      | How much rating? |  10    |
 |    59    |   Zess   |     1      | Recommend This?  |  No    |
 |    59    |   Zess   |     2      | How much rating? |  8     |

有这样的课程(请忽略某些字段):

 class reportlist
    {
        public string MemberID { get; set; }
        public string Username { get; set; }
        public string Name { get; set; }
        public string Email { get; set; }
        public int QuestionID { get; set; }
        public string Question { get; set; }
        public string Answer { get; set; }
        public DateTime Submitted_On { get; set; }
        public int TotalPoint { get; set; }
    }

并有一个 mysql reader 可以将数据添加到报告列表中:

 while (reader.Read())
 {
       reportlist.Add(new reportlist() { MemberID = reader["MemberID"].ToString(), Username = reader["Username"].ToString(),
                        Name = reader["Name"].ToString(), Email = reader["Email"].ToString(), QuestionID = int.Parse(reader["QuestionID"].ToString()), Question = reader["Question"].ToString(),
                        Answer = reader["Answer"].ToString(), Submitted_On = DateTime.Parse(reader["CreationDate"].ToString()), TotalPoint = int.Parse(reader["TotalPoint"].ToString()) });                        
 }

现在卡住了,我尝试使用 Linq 进行查询:

var groupedList = reportlist
           .GroupBy(u => u.QuestionID, u => u.MemberID)
           .ToList();

DataTable dt = new DataTable();

foreach (var group in groupedList)
{
   //add columns, rows to datatable, stuck here
}

不确定如何将这些结果获取到数据表中。基本上,我想将问题分组并使其成为列,并将所有数据添加到数据表中以形成这些结果(示例):

 | MemberID | Username | Recommend This? | How much rating? | 
 | 58       |   John   |      Yes        |       10         | 
 | 59       |   Zess   |      No         |        8         | 

请指导如何获得结果或更好的解决方案?我被困了很长一段时间,因为我不擅长 linq。我确实尝试过四处搜索,结果并不多,可能不太了解它是如何工作的。

附加信息:最终数据表用于 EPPlus 库(生成 excel 电子表格)

【问题讨论】:

    标签: c# mysql asp.net linq datatable


    【解决方案1】:

    显然,您在问题中发布的代码不可能是您的真实代码,因为它具有以下特性,永远不会编译:

     class reportlist { ... }
     reportlist.Add(new reportlist() { ... });
    

    做出一些假设来回答这个问题:

    List<reportlist> list; // the list filled by the data reader.
    

    您可以通过几个步骤制作“数据透视表”(即将行值转换为列):

    // Get unique question info.
    var questions = list
        .GroupBy(x => x.QuestionID)
        .Select(x => new { Id = x.Key, Title = x.First().Question });
    
    // Set up the columns for the data table as a "pivot table" with columns per question.
    DataTable myTable = new DataTable("QuestionsPivotTable");
    var fixedColumns = new [] { 
        new DataColumn("Member ID", typeof(string)),
        new DataColumn("User Name", typeof(string)),
    };
    var questionColumns = questions.Select(x => new DataColumn(x.Title, typeof(string)));
    myTable.Columns.AddRange(fixedColumns.Concat(questionColumns).ToArray());
    

    通过包含“枢轴”问题列的数据表设置,我们可以为每个成员获取一行作为值数组:

    // Get the column values for each member as an array.
    var rows = list
        .GroupBy(x => x.MemberID)
        .Select(x => {
            var memberCols = new object[] { x.Key, x.First().Username };
            var answerCols = questions.Select(q => x.Where(a => a.QuestionID == q.Id).Select(a => a.Answer).FirstOrDefault());
            return memberCols.Concat(answerCols).ToArray();
        });
    

    现在填表很容易:

    // Fill the table.
    foreach (var memberRow in rows)
    {
        var row = myTable.NewRow().ItemArray = memberRow;
        myTable.Rows.Add(row);
    }
    

    在哪里,使用您的示例数据,下面的代码:

    // Show the output
    for (var i = 0; i < myTable.Columns.Count - 1; i++)
        Console.Write("{0}, ", myTable.Columns[i]);
    Console.WriteLine("{0}", myTable.Columns[myTable.Columns.Count - 1]);
    foreach (var row in myTable.AsEnumerable())
        Console.WriteLine(string.Join(", ", row.ItemArray.Select(x => x == null ? "<null>" : x.ToString())));
    

    产生这个输出:

    Member ID, User Name, Recommend This?, How much rating?
    58, John, Yes, 10
    59, Zess, No, 8
    

    【讨论】:

    • 感谢您的解释和代码。谢谢!已经通过它并能够解决我的问题。一定会研究它并应用到接下来的工作中~
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多