Select DISTINCT on DataTable
From:http://weblogs.asp.net/eporter/default.aspx
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

public partial class SelectDistinctDataTable : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
//Create table
DataTable dt = new DataTable("items");
//add two columns to datatable
DataColumn col;
col = new DataColumn("id", typeof(System.Int32));
col.AutoIncrement = true;
dt.Columns.Add(col);
col = new DataColumn("item", typeof(System.String));
dt.Columns.Add(col);
//config AcceptChange
dt.AcceptChanges();
//set primary key
dt.PrimaryKey = new DataColumn[] { dt.Columns["id"] };

DataTable DesTbl = dt.Clone();


DataRow dr;
for (int i = 0; i < 10; i++)
{
dr = dt.NewRow();
dr[1] = "Roboth" + i;
dt.Rows.Add(dr);
}
for (int i = 0; i < 10; i++)
{
dr = dt.NewRow();
dr[1] = "Roboth" + i;
dt.Rows.Add(dr);
}
PrintValues(dt, "before select distinct");
DataTable distTbl = SelectDistinct(dt, new string[] {"item" });
PrintValues(distTbl, "the result for select distinct datatable");

}
private static void PrintValues(DataTable table, string lbl)
{
// Display the values in the supplied DataTable:

System.Web.HttpContext.Current.Response.Write(lbl + "<br />");
foreach (DataRow row in table.Rows)
{
foreach (DataColumn column in table.Columns)
{
System.Web.HttpContext.Current.Response.Write(row[column, DataRowVersion.Current]);
}
System.Web.HttpContext.Current.Response.Write("<br />");
}
}
private static DataTable SelectDistinct(DataTable SourceTable, params string[] FieldNames)
{
object[] lastValues;
DataTable newTable;
DataRow[] orderedRows;

if (FieldNames == null || FieldNames.Length == 0)
throw new ArgumentNullException("FieldNames");

lastValues = new object[FieldNames.Length];
newTable = new DataTable();

foreach (string fieldName in FieldNames)
newTable.Columns.Add(fieldName, SourceTable.Columns[fieldName].DataType);

orderedRows = SourceTable.Select("", string.Join(", ", FieldNames));

foreach (DataRow row in orderedRows)
{
if (!fieldValuesAreEqual(lastValues, row, FieldNames))
{
newTable.Rows.Add(createRowClone(row, newTable.NewRow(), FieldNames));

setLastValues(lastValues, row, FieldNames);
}
}

return newTable;
}

private static bool fieldValuesAreEqual(object[] lastValues, DataRow currentRow, string[] fieldNames)
{
bool areEqual = true;
/*
id username sex
0 1 2
*/
for (int i = 0; i < fieldNames.Length; i++)
{
if (lastValues[i] == null || !lastValues[i].Equals(currentRow[fieldNames[i]]))
{
areEqual = false;
break;
}
}

return areEqual;
}

private static DataRow createRowClone(DataRow sourceRow, DataRow newRow, string[] fieldNames)
{
//id username sex
// 0 1 2
foreach (string field in fieldNames)
newRow[field] = sourceRow[field];

return newRow;
}

private static void setLastValues(object[] lastValues, DataRow sourceRow, string[] fieldNames)
{
//id username,sex
// 0 1 2
for (int i = 0; i < fieldNames.Length; i++)
lastValues[i] = sourceRow[fieldNames[i]];
}


}
In a project I'm doing I needed to basically do a DISTINCT on a couple fields in a DataTable that I had used earlier in code. Did some Google searching and came up with this MS KB on the subject. I was hoping to find it in the Framework, but hey, writing a little extra code never hurt anyway. Looking over the code though I found that I just didn't really like it. Biggest reason being it only took one field. I wanted to be able to pass in n number of fields, so I rewrote it and did a little tweaking to it. Here's what I came up with in both VB and C#
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
public partial class SelectDistinctDataTable : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
//Create table
DataTable dt = new DataTable("items");
//add two columns to datatable
DataColumn col;
col = new DataColumn("id", typeof(System.Int32));
col.AutoIncrement = true;
dt.Columns.Add(col);
col = new DataColumn("item", typeof(System.String));
dt.Columns.Add(col);
//config AcceptChange
dt.AcceptChanges();
//set primary key
dt.PrimaryKey = new DataColumn[] { dt.Columns["id"] };
DataTable DesTbl = dt.Clone();

DataRow dr;
for (int i = 0; i < 10; i++)
{
dr = dt.NewRow();
dr[1] = "Roboth" + i;
dt.Rows.Add(dr);
}
for (int i = 0; i < 10; i++)
{
dr = dt.NewRow();
dr[1] = "Roboth" + i;
dt.Rows.Add(dr);
}
PrintValues(dt, "before select distinct");
DataTable distTbl = SelectDistinct(dt, new string[] {"item" });
PrintValues(distTbl, "the result for select distinct datatable");
}
private static void PrintValues(DataTable table, string lbl)
{
// Display the values in the supplied DataTable:
System.Web.HttpContext.Current.Response.Write(lbl + "<br />");
foreach (DataRow row in table.Rows)
{
foreach (DataColumn column in table.Columns)
{
System.Web.HttpContext.Current.Response.Write(row[column, DataRowVersion.Current]);
}
System.Web.HttpContext.Current.Response.Write("<br />");
}
}
private static DataTable SelectDistinct(DataTable SourceTable, params string[] FieldNames)
{
object[] lastValues;
DataTable newTable;
DataRow[] orderedRows;
if (FieldNames == null || FieldNames.Length == 0)
throw new ArgumentNullException("FieldNames");
lastValues = new object[FieldNames.Length];
newTable = new DataTable();
foreach (string fieldName in FieldNames)
newTable.Columns.Add(fieldName, SourceTable.Columns[fieldName].DataType);
orderedRows = SourceTable.Select("", string.Join(", ", FieldNames));
foreach (DataRow row in orderedRows)
{
if (!fieldValuesAreEqual(lastValues, row, FieldNames))
{
newTable.Rows.Add(createRowClone(row, newTable.NewRow(), FieldNames));
setLastValues(lastValues, row, FieldNames);
}
}
return newTable;
}
private static bool fieldValuesAreEqual(object[] lastValues, DataRow currentRow, string[] fieldNames)
{
bool areEqual = true;
/*
id username sex
0 1 2
*/
for (int i = 0; i < fieldNames.Length; i++)
{
if (lastValues[i] == null || !lastValues[i].Equals(currentRow[fieldNames[i]]))
{
areEqual = false;
break;
}
}
return areEqual;
}
private static DataRow createRowClone(DataRow sourceRow, DataRow newRow, string[] fieldNames)
{
//id username sex
// 0 1 2
foreach (string field in fieldNames)
newRow[field] = sourceRow[field];
return newRow;
}
private static void setLastValues(object[] lastValues, DataRow sourceRow, string[] fieldNames)
{
//id username,sex
// 0 1 2
for (int i = 0; i < fieldNames.Length; i++)
lastValues[i] = sourceRow[fieldNames[i]];
}

}



浙公网安备 33010602011771号