C# 如何更改DataTable结构,使列值位于多列中?
如果我有一个这样结构的数据表:C# 如何更改DataTable结构,使列值位于多列中?,c#,linq,collections,datatable,transpose,C#,Linq,Collections,Datatable,Transpose,如果我有一个这样结构的数据表: emp_num name status session_id 22 john 0 4 22 john 0 5 34 moh 1 3 35 Ran 0 3 35 Ran 0 4 emp_num name status session_id1 session_id2 session_id3
emp_num name status session_id
22 john 0 4
22 john 0 5
34 moh 1 3
35 Ran 0 3
35 Ran 0 4
emp_num name status session_id1 session_id2 session_id3 session_id4 session_id5
22 john 0 0 0 0 1 1
34 moh 1 0 0 1 0 0
35 Ran 0 0 0 1 1 0
如何将其转换为datatable,如下所示:
emp_num name status session_id
22 john 0 4
22 john 0 5
34 moh 1 3
35 Ran 0 3
35 Ran 0 4
emp_num name status session_id1 session_id2 session_id3 session_id4 session_id5
22 john 0 0 0 0 1 1
34 moh 1 0 0 1 0 0
35 Ran 0 0 0 1 1 0
我尝试创建带有循环的自定义数据表,但它不是通用的,我想要一些通用的数据表,因此如果我添加更多列或增加会话数,我不会得到超出范围的异常
using System.Data;
public static class DataTableExtensionMethods
{
public static DataTable TransposeIntegerColumnIntoColumns(this DataTable dt, int indexColumnToEstablishDuplicateRows, int integerColumnIdToTranspose, string transposedColumnName)
{
//Protection if the column to transpose is not an integer or doesn't exist
if (integerColumnIdToTranspose >= dt.Columns.Count) return null;
var columnDataType = dt.Columns[integerColumnIdToTranspose].DataType;
if (columnDataType != typeof(int)) return null;
//Get max sessions number
int maxColumnNumber = 0;
foreach (DataRow dr in dt.Rows)
{
int? number = dr.Field<int?>(integerColumnIdToTranspose);
if (number != null)
{
maxColumnNumber = Math.Max(maxColumnNumber, (int)number);
}
}
//Protection if there are zero rows or the maxColumnNumber is 0
if (dt.Rows.Count == 0 || maxColumnNumber == 0) return null;
//Make a copy of the table so we can remove duplicate rows and add the transposed columns
DataTable result = dt.Copy();
//Add columns to store the session_ids
for (int i = 1; i <= maxColumnNumber; i++)
{
DataColumn dc = new DataColumn(transposedColumnName + i.ToString(), typeof(int));
dc.DefaultValue = 0;
//Possibly make an overloaded method that supports inserting columns
result.Columns.Add(dc);
}
//Remove rows with duplicated employees
for (int i = 0; i < result.Rows.Count; i++)
{
int duplicateRow = GetRowIndexById(result, indexColumnToEstablishDuplicateRows, result.Rows[i][indexColumnToEstablishDuplicateRows].ToString(), i + 1);
if (duplicateRow > -1)
{
result.Rows.RemoveAt(duplicateRow);
}
}
//Populate the transposed columns with values in the integer Column To Transpose
foreach (DataRow dr in dt.Rows)
{
int? sessionNumber = dr.Field<int?>(integerColumnIdToTranspose);
if (sessionNumber == null) continue;
int rowIndex = GetRowIndexById(result, indexColumnToEstablishDuplicateRows, dr[indexColumnToEstablishDuplicateRows].ToString(), 0);
result.Rows[rowIndex][transposedColumnName + sessionNumber.ToString()] = 1; //or +=1 if you want to increment the number
}
//Remove the integerColumnIdToTranspose (again overload this method if you want to keep this column)
result.Columns.RemoveAt(integerColumnIdToTranspose);
return result;
}
//Net 4 implementation with optional parameter
//private static int GetRowIndexById(DataTable dt, int indexColumnToEstablishDuplicateRows, string id, int startLookAtRow = 0)
private static int GetRowIndexById(DataTable dt, int indexColumnToEstablishDuplicateRows, string id, int startLookAtRow)
{
for (int i = startLookAtRow; i < dt.Rows.Count; i++)
{
if (dt.Rows[i][indexColumnToEstablishDuplicateRows].ToString() == id) return i;
}
return -1;
}
}
结果是:
我认为你的方法有根本性的问题。如果员工和会话之间存在一对多关系,则需要有两个表。一个表用于员工,其中每个员工有一行,另一个表用于会话,其中每个会话有一行。每个会话记录都应该有一个“emp_num”将其链接回员工。@Keith:是的,有两个表,我在这两个表之间建立了一个连接,并在datatable中设置结果。现在,我想要一个具有以下结构的报告
emp\u num name status session\u id1 session\u id2 session\u id3…
列的数量取决于session\u id valueOk,将DataTable扩展方法类中的代码复制/粘贴到您的项目中,我使其与.Net 3.5兼容:)我确实测试了这段代码。奇怪的添加对null值的检查是好的,尽管我不确定这行代码如何引发异常:int?sessionNumber=dr.Field(integercolumnidtottranspose)
在添加列session\u id0之前。感谢您的提示。在我的代码中,请参见如何为添加以1:开头的列(int i=1;i不,我没有更改代码,但有时我会有这样的数据34 Moh 0 null
因为数据表结果来自outer join
对所有编辑表示歉意,我已经用null会话测试了此方法,它是有效的。如果遇到任何其他问题,请告诉我。干杯