Need help. I have 6 columns in a datatable. I've converted it to a dataview, and sorted it by all six, then updated the datatable accordingly. I need to group rows when the values in the last 4 columns are identical and place them in their own, unique tables that I can use later, removing them from the original table.
My columns are: CurveNumber, ObjectId, Length, Radius, Delta, and Tangent.
Thanks for any help you can provide.
another solution here
DataTable dt = new DataTable();
dt.Columns.AddRange(new DataColumn[] { new DataColumn("CurveNumber"), new DataColumn("ObjectId"), new DataColumn("Length"),
new DataColumn("Radius"), new DataColumn("Delta"), new DataColumn("Tangent") });
dt.Rows.Add(new object[] { "1","0851ax","20","20","20","20" });
dt.Rows.Add(new object[] { "2", "0852ab", "20", "20", "20", "20" });
dt.Rows.Add(new object[] { "3", "0853ac", "25", "32", "12", "10" });
dt.Rows.Add(new object[] { "4", "0854ad", "12", "31", "15", "20" });
dt.Rows.Add(new object[] { "5", "0855ca", "20", "20", "20", "20" });
dt.Rows.Add(new object[] { "6", "0856ad", "25", "32", "12", "10" });
//Group by distinct 4 column
var GroupBy4ColumnDistinct = dt.Rows.Cast<DataRow>()
.ToLookup(x => (Convert.ToString(x["Length"]) + Convert.ToString(x["Radius"]) + Convert.ToString(x["Delta"]) + Convert.ToString(x["Tangent"])).GetHashCode())
.Select(x => new { key = x.Key, values = x.Select(y => Convert.ToString(y["CurveNumber"])).ToList() }).ToList();
// add new table to dataset. dataset contain 3 table as shown in our sample output
DataSet ds = new DataSet();
foreach (var item in GroupBy4ColumnDistinct)
{
DataView dv = new DataView(dt);
dv.RowFilter = " CurveNumber in ( " + string.Join(",", item.values) + " )";
ds.Tables.Add(dv.ToTable());
}</pre>
An approach - start with a DataView and use its .ToTable() method to first obtain a unique collection of values for your last four columns. Then loop through it looking for matches in the original table (source at: https://dotnetfiddle.net/PlAZSi):
// Initial table set up and population
DataTable originalTable = new DataTable("originaltable");
originalTable.Columns.Add("CurveNumber", (123).GetType());
originalTable.Columns.Add("ObjectID", ("String").GetType());
originalTable.Columns.Add("Length", (123).GetType());
originalTable.Columns.Add("Radius", (123).GetType());
originalTable.Columns.Add("Delta", (123).GetType());
originalTable.Columns.Add("Tangent", (123).GetType());
originalTable.Rows.Add(new object[] { 1, "0851ax", 20, 20, 20, 20} );
originalTable.Rows.Add(new object[] { 2, "0852ab", 20, 20, 20, 20} );
originalTable.Rows.Add(new object[] { 3, "0853ac", 25, 32, 12, 10} );
originalTable.Rows.Add(new object[] { 4, "0854ad", 12, 31, 15, 20} );
originalTable.Rows.Add(new object[] { 5, "0855ca", 20, 20, 20, 20} );
originalTable.Rows.Add(new object[] { 6, "0856ad", 25, 32, 12, 10} );
// Create a new datatable containing the unique values
// for the four columns in question
DataTable uniqueValues = (new DataView(originalTable))
.ToTable(true, new string[] {"Length",
"Radius",
"Delta",
"Tangent"});
// Create a DataSet of DataTables each one containing the grouped
// rows based on matches on the four columns in question.
DataSet groupedRows = new DataSet("groupedRows");
foreach (DataRow uniqueValue in uniqueValues.Rows) {
// Create the individual table of grouped rows based on the
// structure of the original table
DataTable groupTable = originalTable.Clone();
groupTable.TableName = String.Format("{0}-{1}-{2}-{3}",
uniqueValue["Length"],
uniqueValue["Radius"],
uniqueValue["Delta"],
uniqueValue["Tangent"]);
// Fetch the rows from the original table based on matching to the
// unique combination of four columns
DataRow[] groupRows = originalTable.Select(String.Format(" Length = {0} AND Radius = {1} AND Delta = {2} AND Tangent = {3} ",
uniqueValue["Length"],
uniqueValue["Radius"],
uniqueValue["Delta"],
uniqueValue["Tangent"]));
// Add each matched row into the individual grouped DataTable
foreach (DataRow groupRow in groupRows) {
groupTable.Rows.Add(groupRow.ItemArray);
}
// Finally, add the DataTable to the DataSet
groupedRows.Tables.Add(groupTable);
}
I would like to point out that there is, very likely, a much more elegant solution using LINQ. However, this should get you where you need to be.
Related
I have got this situation with a datatable like this
C1 C2 C3
A AA 4
BB 6
B CC 3
DD 3
EE 4
C FF 5
GG 5
and my output should be like this
C1 C2 C3
A AA,BB 10
B CC,DD,EE 10
C FF,GG 10
How can i group by the column with the space till the next value comes up
What i did was i took all the row itemarray and then using some string manipulation and regex got the row value as for the first two values like this and assigned to a variable in a query using Let
A,AA,BB,10|B,CC,DD,EE,10 but then i cannot add it using the
**DT.clone.rows.Add(x.split("|"c))* method as there its not incrementing and adding the whole joined string
Any other input where i can manipulate and add it (P.S i know linq is querying language)
Thank you for your time
You can use .GroupBy to get result needed
Here is your class:
public class Data
{
public string C1 { get; set; }
public string C2 { get; set; }
public int C3 { get; set; }
}
Imagine that you have list of Data objects, so your GroupBy expression will be following:
var result = list.GroupBy(g => g.C1, (a, b) => new {C1 = a, C2 = b.ToList()})
.Select(g => new
{
g.C1,
C2 = string.Join(",", g.C2.Select(m => m.C2)),
C3 = g.C2.Sum(m => m.C3)
})
.ToList();
A simple .GroupBy can give you expected result, Edited to handle Null or WhiteSpace Columns
var res = ListModel.Where(e => !string.IsNullOrWhiteSpace(e.C1)
&& !string.IsNullOrWhiteSpace(e.C2))
.GroupBy(e => e.C1).Select(e => new
{
e.Key,
c2 = string.Join(",", e.Select(x => x.C2).ToList()),
c3 = e.Sum(x => x.C3)
}).ToList();
Hello All first of all Thank you for your time and effort i Did this use case using this code
This gave me all row item array in string and than in the end with a little Split method i was able to add it to my datatable
String.Join("|",(System.Text.RegularExpressions.Regex.Replace(String.Join("|",(From roww In DT.AsEnumerable() Select String.Join(",",roww.ItemArray) ).ToList),"\|,",",")).Split("|"c).
Select(Function(q)CStr(q)+","+CStr(String.join("|",System.Text.RegularExpressions.Regex.Matches(CStr(q),"\d+").Cast(Of match)).Split("|"c).Sum(Function(r) CInt(r) ))).tolist),",\d+,",",")```
Try following code which is tested
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
DataTable dt1 = new DataTable();
dt1.Columns.Add("C1", typeof(string));
dt1.Columns.Add("C2", typeof(string));
dt1.Columns.Add("C3", typeof(int));
dt1.Rows.Add(new object[] { "A", "AA", 4});
dt1.Rows.Add(new object[] { null, "BB", 6});
dt1.Rows.Add(new object[] { "B", "CC", 3});
dt1.Rows.Add(new object[] { null, "DD", 3});
dt1.Rows.Add(new object[] { null, "EE", 4});
dt1.Rows.Add(new object[] { "C", "FF", 5});
dt1.Rows.Add(new object[] { null, "GG", 5});
//replace nulls in column 1 with actual values
string previous = "";
foreach(DataRow row in dt1.AsEnumerable())
{
if (row.Field<string>("C1") == null)
{
row["C1"] = previous;
}
else
{
previous = row.Field<string>("C1");
}
}
DataTable dt2 = dt1.Clone();
var groups = dt1.AsEnumerable().GroupBy(x => x.Field<string>("C1")).ToList();
foreach (var group in groups)
{
dt2.Rows.Add(new object[] {
group.Key,
string.Join(",", group.Select(x => x.Field<string>("C2"))),
group.Select(x => x.Field<int>("C3")).Sum()
});
}
}
}
}
Yet another way using Skip, TakeWhile, and GroupBy extensions:
DataTable dt1 = new DataTable();
dt1.Columns.Add("C1", typeof(string));
dt1.Columns.Add("C2", typeof(string));
dt1.Columns.Add("C3", typeof(int));
//The output table.
DataTable dt2 = dt1.Clone();
dt1.Rows.Add(new object[] { "A", "AA", 3 });
dt1.Rows.Add(new object[] { null, "BB", 6 });
dt1.Rows.Add(new object[] { "B", "CC", 3 });
dt1.Rows.Add(new object[] { null, "DD", 3 });
dt1.Rows.Add(new object[] { null, "EE", 4 });
dt1.Rows.Add(new object[] { "C", "FF", 5 });
dt1.Rows.Add(new object[] { null, "GG", 6 });
var rows = dt1.Rows.Cast<DataRow>().AsEnumerable();
foreach (var row in rows.Where(r => r.Field<string>("C1") != null))
{
var indx = dt1.Rows.IndexOf(row) + 1;
var q = rows
.Skip(indx)
.TakeWhile(t => t.Field<string>("C1") == null)
.GroupBy(g => g.Field<string>("C1"))
.Select(g => new
{
C1 = row.Field<string>("C1"),
C2 = $"{row.Field<string>("C2")}, {string.Join(", ", g.Select(s => s.Field<string>("C2")))}",
C3 = row.Field<int>("C3") + g.Sum(s => s.Field<int>("C3")),
}).FirstOrDefault();
if (q != null)
dt2.Rows.Add(q.C1, q.C2, q.C3);
}
dataGridView1.DataSource = null;
dataGridView1.DataSource = dt2;
The idea behind this snippet is to:
Get the complete rows and iterate through them.
For each complete row, we get it's index from the original DataTable and add 1 to make a starting search point for the incomplete rows. The Skip extension is the method to achieve that.
The TakeWhile extension function gets the incomplete rows and stops at the next complete row.
The GroupBy extension function groups the incomplete rows to concatenate their C2 values and sum their C3 values, add the results to the values of the complete row and create a temporary anonymous object to hold these values.
Extract the anonymous object and add a new DataRow to the output DataTable.
And finally, bind the output DataTable to a DGV.
Happy 2020 for all.
I have two DataTables being filled.
DT1 and DT2
Each DataTable has the same column headers. However, DT2 may or may not have the same amount of rows.
ID | Type | Value
I need the new Table to add Rows as necessary based on the number of results that are returned in the "Type" column and set DT3 rows ID = DT1.ID and Value to "N/A"
DT1 DT2 DT3
ID | Type | Value ID | Type | Value ID | Type | Value
1 ItemCost 5000 27 ItemCost 3800 27 ItemCost 3800
2 TravCost 5700 28 TravCost 4851 28 TravCost 4851
3 UpCharge 3600 3 UpCharge N/A
4 TaxCost 7000 4 TaxCost N/A
Here is my code for this issue:
DataTable dt1 = new DataTable();
dt1.Columns.Add("ID");
dt1.Columns.Add("Type");
dt1.Columns.Add("Value");
dt1.Rows.Add(new Object[] { "1", "ItemCost", "5000" });
dt1.Rows.Add(new Object[] { "2", "TravCost", "5700" });
dt1.Rows.Add(new Object[] { "3", "UpCharge", "3600" });
dt1.Rows.Add(new Object[] { "4", "TaxCost", "7000" });
DataTable dt2 = new DataTable();
dt2.Columns.Add("ID");
dt2.Columns.Add("Type");
dt2.Columns.Add("Value");
dt2.Rows.Add(new Object[] { "27", "ItemCost", "3800" });
dt2.Rows.Add(new Object[] { "28", "TravCost", "4851" });
DataTable dt3 = new DataTable();
dt3 = dt2.Clone();
foreach (DataRow item in dt2.Rows)
{
dt3.Rows.Add(new object[] { item["ID"], item["Type"], item["Value"] });
}
foreach (DataRow item in dt1.Rows)
{
DataRow[] drs = dt3.Select("Type='" + item["Type"].ToString() + "'");
if (drs.Count() == 0)
{
dt3.Rows.Add(new object[] { item["ID"], item["Type"], "N/A" });
}
}
Firstly, this is for a legacy application, so I cannot radically change any logic.
I have database with two tables that do not have any relationships. I asked if I change this, but was told I cannot.
These tables can be described as
Create Table T1
[doc_id] [int] NOT NULL, -- Primary Key
[customer_acc_no] [varchar](16) NULL,
[gcompany] [varchar](30) NULL,
....
extra fields
and table
Create Table T2
[UserURN] [int] NOT NULL, -- All three fields make up
[AccountNumber] [varchar](20) NOT NULL, -- the primary key
[Company] [varchar](50) NOT NULL,
....
extra fields
As you can see, not only are the field names different, but they have different lengths too.
I am using the Repository and UnitOfWork patterns. So far I have managed to code the following:
private IRepository<T1> _t1Repository;
private IRepository<T2> _t2Repository;
These are populated within the constructor.
Next I use the following code to configure get a queryable repository.
var retVal = _t1Repository.Queryable();
From this, I am trying to add the following join.
from q in T1
join w in T2
on new { X1 = q.gcompany, X2 = q.Customer_acc_no }
equals new { X1 = w.Company, X2 = w.AccountNumber }
I am thinking it would be along the lines of:
var query = T1.GroupJoin(T2,
c => c.gcompany,
o => o.Company,
(c, result) => new Result(c.doc_id, result))
.GroupJoin(T2,
c => c.Customer_acc_no,
o => o.AccountNumber ,
(c, result) => new Result(c.doc_id, result));
but i'm not sure as all attempts so far end in errors within visual studio.
See code below :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
namespace ConsoleApplication42
{
class Program
{
static void Main(string[] args)
{
DataTable dt1 = new DataTable();
dt1.Columns.Add("doc_id", typeof(int));
dt1.Columns.Add("customer_acc_no", typeof(string));
dt1.Columns.Add("gcompany", typeof(string));
dt1.Rows.Add(new object[] { 1, "100", "abc" });
dt1.Rows.Add(new object[] { 2, "100", "def" });
dt1.Rows.Add(new object[] { 3, "100", "def" });
dt1.Rows.Add(new object[] { 4, "101", "abc" });
dt1.Rows.Add(new object[] { 5, "101", "ghi" });
dt1.Rows.Add(new object[] { 6, "102", "jkl" });
dt1.Rows.Add(new object[] { 7, "102", "abc" });
dt1.Rows.Add(new object[] { 8, "102", "def" });
dt1.Rows.Add(new object[] { 9, "103", "abc" });
dt1.Rows.Add(new object[] { 10, "103", "abc" });
DataTable dt2 = new DataTable();
dt2.Columns.Add("UserURN", typeof(int));
dt2.Columns.Add("AccountNumber", typeof(string));
dt2.Columns.Add("Company", typeof(string));
dt2.Rows.Add(new object[] { 11, "100", "abc" });
dt2.Rows.Add(new object[] { 12, "100", "def" });
dt2.Rows.Add(new object[] { 13, "100", "def" });
dt2.Rows.Add(new object[] { 14, "101", "abc" });
dt2.Rows.Add(new object[] { 15, "101", "ghi" });
dt2.Rows.Add(new object[] { 16, "102", "jkl" });
dt2.Rows.Add(new object[] { 17, "102", "abc" });
dt2.Rows.Add(new object[] { 18, "102", "def" });
dt2.Rows.Add(new object[] { 19, "103", "abc" });
dt2.Rows.Add(new object[] { 20, "103", "abc" });
var results = from r1 in dt1.AsEnumerable()
join r2 in dt2.AsEnumerable() on
new { x1 = r1.Field<string>("customer_acc_no"), x2 = r1.Field<string>("gcompany") } equals
new { x1 = r2.Field<string>("AccountNumber"), x2 = r2.Field<string>("Company") }
select new { t1 = r1, t2 = r2 };
}
}
}
My first DataTable is
Name | Value
---------------+----------
A | 12
B | 22
and i want this table as
A | B
---------------+----------
12 | 22
How to resolve this,please help me i tried a lot but i didn't get.Thank You in Advance.
You can convert rows into column using below line of code:
DataTable Pivot(DataTable table, string pivotColumnName)
{
// TODO make sure the table contains at least two columns
// get the data type of the first value column
var dataType = table.Columns[1].DataType;
// create a pivoted table, and add the first column
var pivotedTable = new DataTable();
pivotedTable.Columns.Add("Row Name", typeof(string));
// determine the names of the remaining columns of the pivoted table
var additionalColumnNames = table.AsEnumerable().Select(x => x[pivotColumnName].ToString());
// add the remaining columns to the pivoted table
foreach (var columnName in additionalColumnNames)
pivotedTable.Columns.Add(columnName, dataType);
// determine the row names for the pivoted table
var rowNames = table.Columns.Cast<DataColumn>().Select(x => x.ColumnName).Where(x => x != pivotColumnName);
// fill in the pivoted data
foreach (var rowName in rowNames)
{
// get the value data from the appropriate column of the input table
var pivotedData = table.AsEnumerable().Select(x => x[rowName]);
// make the rowName the first value
var data = new object[] { rowName }.Concat(pivotedData).ToArray();
// add the row
pivotedTable.Rows.Add(data);
}
return pivotedTable;
}
In case you have any problem or query please feel free to ask me.
Here is a pivot table
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
namespace ConsoleApplication33
{
class Program
{
static void Main(string[] args)
{
DataTable dt = new DataTable();
dt.Columns.Add("Name", typeof(string));
dt.Columns.Add("Value", typeof(int));
dt.Columns.Add("Date", typeof(DateTime));
dt.Rows.Add(new object[] {"A", 100, DateTime.Parse("12/1/16")});
dt.Rows.Add(new object[] { "A", 101, DateTime.Parse("12/2/16") });
dt.Rows.Add(new object[] { "A", 102, DateTime.Parse("12/3/16") });
dt.Rows.Add(new object[] { "A", 103, DateTime.Parse("12/4/16") });
dt.Rows.Add(new object[] { "B", 104, DateTime.Parse("12/1/16") });
dt.Rows.Add(new object[] { "B", 110, DateTime.Parse("12/2/16") });
dt.Rows.Add(new object[] { "B", 114, DateTime.Parse("12/3/16") });
dt.Rows.Add(new object[] { "B", 112, DateTime.Parse("12/4/16") });
dt.Rows.Add(new object[] { "B", 100, DateTime.Parse("12/5/16") });
dt.Rows.Add(new object[] { "C", 120, DateTime.Parse("12/1/16") });
dt.Rows.Add(new object[] { "C", 130, DateTime.Parse("12/2/16") });
dt.Rows.Add(new object[] { "C", 140, DateTime.Parse("12/3/16") });
dt.Rows.Add(new object[] { "C", 150, DateTime.Parse("12/4/16") });
dt.Rows.Add(new object[] { "C", 160, DateTime.Parse("12/5/16") });
dt.Rows.Add(new object[] { "C", 101, DateTime.Parse("12/6/16") });
string[] uniqueNames = dt.AsEnumerable().Select(x => x.Field<string>("Name")).Distinct().ToArray();
var groups = dt.AsEnumerable().GroupBy(x => x.Field<DateTime>("Date")).ToList();
DataTable pivot = new DataTable();
pivot.Columns.Add("Date", typeof(DateTime));
foreach (var name in uniqueNames)
{
pivot.Columns.Add(name, typeof(string));
}
foreach (var group in groups)
{
DataRow newRow = pivot.Rows.Add();
newRow["Date"] = group.Key;
foreach (DataRow row in group)
{
newRow[row.Field<string>("Name")] = row.Field<int>("Value");
}
}
}
}
}
I have 2 DataTable with the following columns:
Table 1
Title
NUMBER
Sub_num1
Sub_num2
Table 2
NUMBER
Sub_num1
Sub_num2
In Table 2 Combination of NUMBER, Sub_num1 and Sub_num2 is unique. Can be Many NUMBERS, but with different set of Sub1 and Sub2.
In Table 1 Title is unique. A couple titles can have the same NUMBER, but again different set of Subs.
I need to loop through Table 2 and check if Table 1 has exact match with all 3 columns, then get this title, if not I need to get all Titles that have this NUMBER.
What is the best and fastest way to do this search? On the top of my head I have only next:
Loop through records in Table 2 and for each record loop through Table 1 and check for match, but I think that this process can be very resource-intensive...
Any help, please?
UPDATE
Example:
var dt1 = new DataTable("Table 1");
dt1.Columns.Add("title", typeof(string));
dt1.Columns.Add("number", typeof(int));
dt1.Columns.Add("subnum1", typeof(int));
dt1.Columns.Add("subnum2", typeof(int));
dt1.Rows.Add(new object[] { "a", 1111, 1, 1 }); // Exact match!
dt1.Rows.Add(new object[] { "b", 2222, 1, 1 }); // Only NUMBER match
dt1.Rows.Add(new object[] { "b", 2222, 2, 2 }); // Only NUMBER match
dt1.Rows.Add(new object[] { "d", 3333, 1, 1 }); // Exact match!
dt1.Rows.Add(new object[] { "d", 3333, 1, 2 });
dt1.Rows.Add(new object[] { "d", 3333, 2, 1 });
var dt2 = new DataTable("Table 2");
dt2.Columns.Add("number", typeof(int));
dt2.Columns.Add("subnum1", typeof(int));
dt2.Columns.Add("subnum2", typeof(int));
dt2.Rows.Add(new object[] { 1111, 1, 1 }); // Exact match!
dt2.Rows.Add(new object[] { 2222, "", 5 }); // Only NUMBER match
dt2.Rows.Add(new object[] { 3333, 1, 1 }); // Exact match!
dt2.Rows.Add(new object[] { 3333, "", "" }); // Only NUMBER match
SO I'm looping through Table 2:
foreach (DataRow row in dt2.Rows)
{
// HERE Should be logic and search
}
RESULT should be:
If match print title, if not print ALL titleS with number, that match, so:
1. "a", 1111, 1, 1
2.1 "b", 2222, 1, 1
2.2 "b", 2222, 2, 2
3. "d", 3333, 1, 1
4.1 "d", 3333, 1, 1
4.2 "d", 3333, 1, 2
4.3 "d", 3333, 2, 1
One possibility would be to use the DataTable class build in filtering. You can define a dynamic filter and apply it to the DataTable object. The dynamic filter language is something like a subset of SQL, it has LIKE and other SQL keywords. An example of filtering code:
var dt = new DataTable("test");
dt.Columns.Add("A", typeof(string));
dt.Columns.Add("B", typeof(string));
dt.Rows.Add(new object[] { "a", "1" });
dt.Rows.Add(new object[] { "a", "2" });
var rows = dt.Select("B = '2'");
This way you can define the filter and apply it to both tables and compare only the result set and not every entry. The result is an array of Rows.
I used it in a project, that has DataTable objects containing more than 2K entries each and the performance is really good.
Another possibility would be to use LINQ to filter the data. You can query the DataTable's rows like this:
var rows = (from DataRow dr in dt.Rows
where dr["B"] == "2"
select dr).ToList();
This query returns the same result as the direct filtering. You can apply again the same approach here to check the mathching result only.
If i understood your question correctly, a possible solution to your problem could look like this:
// test DataTable objects for the example
var dt1 = new DataTable("Table 1");
dt1.Columns.Add("title", typeof(string));
dt1.Columns.Add("number", typeof(int));
dt1.Columns.Add("subnum1", typeof(int));
dt1.Columns.Add("subnum2", typeof(int));
dt1.Rows.Add(new object[] { "a", 1111, 1, 1 }); // Exact match!
dt1.Rows.Add(new object[] { "b", 2222, 1, 1 }); // Only NUMBER match
dt1.Rows.Add(new object[] { "b", 2222, 2, 2 }); // Only NUMBER match
dt1.Rows.Add(new object[] { "d", 3333, 1, 1 }); // Exact match!
dt1.Rows.Add(new object[] { "d", 3333, 1, 2 });
dt1.Rows.Add(new object[] { "d", 3333, 2, 1 });
var dt2 = new DataTable("Table 2");
dt2.Columns.Add("number", typeof(int));
dt2.Columns.Add("subnum1", typeof(int));
dt2.Columns.Add("subnum2", typeof(int));
dt2.Rows.Add(new object[] { 1111, 1, 1 }); // Exact match!
dt2.Rows.Add(new object[] { 2222, 0, 5 }); // Only NUMBER match
dt2.Rows.Add(new object[] { 3333, 1, 1 }); // Exact match!
dt2.Rows.Add(new object[] { 3333, 0, 0 }); // Only NUMBER match
foreach (DataRow row in dt1.Rows)
{
var matches = dt2.Select(string.Format("number = {0} and subnum1 = {1} and subnum2 = {2}", row["number"], row["subnum1"], row["subnum2"]));
if (matches.Count() > 0)
{
Console.WriteLine(row["title"]);
}
else
{
var fallback = dt2.Select(string.Format("number = {0}", row["number"]));
if (fallback.Count() > 0)
{
Console.WriteLine(" > " + row["title"]);
}
}
}
The output in this case is:
a
> b
> b
d
> d
> d
What values shoule be written to the output is up to you - at the point where the match is found you have all that you need.