Distinct records in DataTable - c#

I want to get distinct records based on some fields. I'm using the following method:
string[] TobeDistinct = { "PKID" };
DataTable dtDistinct = GetDistinctRecords(ds.Tables[0], TobeDistinct);
DataSet ds2 = new System.Data.DataSet();
ds2.Tables.Add(dtDistinct);
public static DataTable GetDistinctRecords(DataTable dt, string[] Columns)
{
DataTable dtUniqRecords = new DataTable();
dtUniqRecords = dt.DefaultView.ToTable(true, Columns);
return dtUniqRecords;
}
This gives me the distinct records, but only two records come. Only two distinct PKID will come. For example, I have multiple records with PKID 10,12,14,16, but the result is 2 rows with PKID 10 and 12. More two rows are not there, but should be there. What do I need to do?
I follow this article: http://www.codeproject.com/Tips/153008/Select-DISTINCT-records-based-on-specified-fields

You can use like follows
DataView view = new DataView(table);
DataTable distinctValues = view.ToTable(true, "Column1", "Column2" ...);
More detail
How to select distinct rows in a datatable and store into an array

Can you try this?
var myResult = dt.AsEnumerable().Select(c => (DataRow)c["MyColumn"]).Distinct().ToList();

Related

Select all columns after filtering Distinct rows based on few columns from a Datatable in c#

I gone through similar questions posted here but didn't find the solution of my problem.
I have a datatable in C# which contains duplicate rows like below:
Now, I have to apply a filter which finds all distinct rows based on Last 2 highlighted columns but in final result set I have to return all columns.
Also, I'll get an ADDRESS_ID whose corresponding row should be
returned and duplicates should be removed.
DataView view = new DataView(ds.Tables[0]);
DataTable distinctValues = view.ToTable(true, "ADDR_LINE_1", "ADDR_LINE_2", "ADDR_LINE_3", "CITY", "STATE", "ZIP", "BOX_NUMBER");
This code is returning 2 rows but not all columns.
Also used this code:
DataTable dtUniqRecords = new DataTable();
dtUniqRecords = ds.Tables[0].DefaultView.ToTable(true, "RELATE_CODE", "ADDRESS_TYPE", "ADDRESS_CODE", "ADDRESS_ID", "ADDR_LINE_1", "ADDR_LINE_2", "ADDR_LINE_3", "CITY", "STATE", "ZIP", "BOX_NUMBER");
But this is returning all rows with duplicates.
You can use GroupBy to filter out duplicate values:
var dt = ds.Tables[0];
var distinct = dt.AsEnumerable()
.GroupBy(g => new
{
Address1 = g.Field<string>("ADDR_LINE_1"),
Address2 = g.Field<string>("ADDR_LINE_2")
// any other fields you need to group by
})
.Select(g => g.First()) // select first group including all columns
.CopyToDataTable();

Select distinct DataTable rows

I have a DataTable where sometimes values in all columns in two or more rows repeat. I would like to get distinct DataTable. The solutions from here and here don't work for me because I have many columns and depending on some conditions, the number of columns changes.
I was thinking maybe something like this
System.Data.DataTable table = new System.Data.DataTable(); // already fulfilled table
DataView view = new DataView(table);
var tableDistinct = view.ToTable(true, table.Columns);
But I can't pass table.Columns as an argument.
I don't know what's going wrong because you haven't said what's not working. However, you could use LINQ(-TO-DataTable):
table = table.AsEnumerable()
.GroupBy(r => new{ Col1 = r["Col1"], Col2 = r["Col2"], Col3 = r["Col3"] })
.Select(g => g.First())
.CopyToDataTable();
Change the columns in the anonymous type according to your column-list.
The ToTable access a list of string params, the following should convert all your columns to array of string so you don't have to enter them manually
System.Data.DataTable table = new System.Data.DataTable(); // already fulfilled table
DataView view = new DataView(table);
var tableDistinct = view.ToTable(true, table.Columns.Cast<DataColumn>().Select(z=>z.ColumnName).ToArray());

How to copy only required rows of old DataTable to the new DataTable rows having different structure?

I have a requirement where I need to copy the existing DataTable rows/values to the new DataTable,
New DataTable is of custom(different column names) structure/schema as we need this new DataTable data to be exported to Excel file later.
To copy the required column values to the new DataTable I have created string Array which contains required column names(columns from which we need to copy data to new DataTable) of existing DataTable, given below.
string[] selectedColumns = new[] { "SUPPLIER_NAME", "SUPPLIER_NO", "CONFIRMATION_NO", "RELEASE_NO", "WCO_INVOICE_NO",
"CUSTOMER_BILLED", "BALANCE_TOBILL", "SUPP_INVOICE_NO", "SUPPLIER_PAID", "BALANCE_COST" }; //TODO Add columns "WCO_INVOICE_DATE", "SUPPLIER_INVOICE_DATE" later.
For getting the required DataTable, I have created a method which will be called like below by passing existing DataTable and selected columns of existing DataTable column names as an parameters.
DataTable _dtPrjLedgerExportData = ControllerClass.dtProjectLedgerExport(dtfilter, selectedColumns);
ControllerClass Class dtProjectLedgerExport method will return the newly created DataTable i.e. DataTable with the customize Column names and the values pulled from existing DatTable,
New DataTable additionally contain two new columns (WCO_Invoice_Date, Supplier_Invoice_Date) with default blank values (set from the code).
public static DataTable dtProjectLedgerExport(DataTable dtToExport, string[] selectedColumns)
{
DataTable dt = new DataTable();
dt.Columns.Add("Supplier");
dt.Columns.Add("Supplier_No");
dt.Columns.Add("Confirmation_Number");
dt.Columns.Add("Release_Number");
dt.Columns.Add("WCO_Invoice_No");
dt.Columns.Add("WCO_Invoice_Date");
dt.Columns.Add("Customer_Billed_Amt");
dt.Columns.Add("Balance_Remaining_to_Bill");
dt.Columns.Add("Supplier_Invoice_Number");
dt.Columns.Add("Supplier_Invoice_Date");
dt.Columns.Add("Supplier_Paid_Amt");
dt.Columns.Add("Remaining_Cost_Dollar_Balance");
//temporarily set default value for non-existing rows
dt.Columns["WCO_Invoice_Date"].DefaultValue = string.Empty;
dt.Columns["Supplier_Invoice_Date"].DefaultValue = string.Empty;
//Copy rows to dt
if (dtToExport != null && dtToExport.Rows.Count > 0)
dt = new DataView(dtToExport).ToTable(false, selectedColumns);
return dt;
}
Problem:
The above code is not working as expected it is returning Data of existing DataTable with the same structure.
What changes are required in above code to get the expected result?
I'd use this approach:
public static DataTable DtProjectLedgerExport(DataTable dtToExport, string[] selectedColumns, params string[] additionalColumns)
{
DataTable dt = dtToExport.Copy(); // add columns and data
List<DataColumn> removeColumns = dt.Columns.Cast<DataColumn>()
.Where(c => !selectedColumns.Contains(c.ColumnName, StringComparer.InvariantCultureIgnoreCase))
.ToList();
removeColumns.ForEach(dt.Columns.Remove);
foreach (string colName in additionalColumns)
{
DataColumn newColumn = new DataColumn(colName);
newColumn.DefaultValue = string.Empty;
dt.Columns.Add(newColumn);
}
return dt;
}
After stating in the comments that you have different column names in each table...(Seriously that's a critical piece of information lol)! The only way is to basiaclly map the values yourself for each column like so.
public static DataTable dtProjectLedgerExport(DataTable dtToExport)
{
DataTable dt = new DataTable();
dt.Columns.Add("Supplier");
dt.Columns.Add("Supplier_No");
dt.Columns.Add("Confirmation_Number");
dt.Columns.Add("Release_Number");
dt.Columns.Add("WCO_Invoice_No");
dt.Columns.Add("WCO_Invoice_Date");
dt.Columns.Add("Customer_Billed_Amt");
dt.Columns.Add("Balance_Remaining_to_Bill");
dt.Columns.Add("Supplier_Invoice_Number");
dt.Columns.Add("Supplier_Invoice_Date");
dt.Columns.Add("Supplier_Paid_Amt");
dt.Columns.Add("Remaining_Cost_Dollar_Balance");
foreach (var expRow in dtToExport.Rows)
{
var row = dt.NewRow();
row["Supplier"] = expRow["Supplier_Name"];
//repeat for all columns you want.
dt.Rows.Add(row);
}
return dt;
}
Well, of course, because you finally override dt completely. You should enumerate the rows in dtToExport in a loop and create new rows in dt and assign the values for every field you need.

To display distinct record from datatable on the basis of particular columns but result should be include all columns

i want to get distinct rows from dt on the basis of particulars columns but result should be displayed with all columns.
Here is code this returning all distinct rows but not binding "Quantity" column of default table:
public static DataTable GetDistinctRecords(DataTable dt)
{
DataView view = new DataView(dt);
DataTable distinctValues = dt.DefaultView.ToTable(true, "ContainerCode", "ProductSKU", "CompanyId", "YearId", "MonthId");
return distinctValues;
}
My datatable dt has "ContainerCode", "ProductSKU", "CompanyId", "YearId", "MonthId","Quantity" this columns,i want distict record except using Quatity but my new datatable should display this quantity column.

Return Multiple DataTable in C# 2005

I have table1 and table2 in a class..
public DataTable sampletable (DataTable table1,DataTable table2)
{
// How to return the two table(table1 and table2)
}
Advance thank you
public DataTable[] sampletable (DataTable table1,DataTable table2)
{
return new DataTable[] { table1, table2 };
}
Use an array. And to retrieve a particular table:
DataTable[] dtArray = sampletable (YourFirstDt, YourSecondDt);
DataTable table1 = dtArray[0];
DataTable table2 = dtArray[1];
Assuming they have the same schema, you can use the DataTable.Merge Method
public DataTable sampletable(DataTable table1, DataTable table2)
{
table1.Merge(table2);
return table1;
}
The Merge method is used to merge two DataTable objects that have
largely similar schemas. A merge is typically used on a client
application to incorporate the latest changes from a data source into
an existing DataTable. This allows the client application to have a
refreshed DataTable with the latest data from the data source.
The merge operation takes into account only the original table, and the
table to be merged. Child tables are not affected or included. If a
table has one or more child tables, defined as part of a relationship,
each child table must be merged individually.
When merging a new source DataTable into the target, any source rows
with a DataRowState value of Unchanged, Modified, or Deleted, is
matched to target rows with the same primary key values. Source rows
with a DataRowState value of Added are matched to new target rows with
the same primary key values as the new source rows.
You can use DataSet , Create a new DataSet and Add the multiple tables to it ,
For Eg-
DataSet Ds = new DataSet();
DataTable Dt1= new DataTable();
Ds.Tables.Add(Dt1)
you can add multiple tables and to access the datatable you can use the index ( eg -
Ds.Tables[0])
Hope this answers your question!!.
public DataSet Getdatasettables()
{
DataSet ds = new DataSet();
DataTable dt1 = new DataTable();
DataTable dt2 = new DataTable();
ds.Tables.Add(dt1);
ds.Tables.Add(dt2);
return ds;
}

Categories