Select DISTINCT on DataTable

From: http://weblogs.asp.net/eporter/default.aspx

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]];
    }



}

你可能感兴趣的:(Datatable)