0

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
4

1 回答 1

3

一种可能性是在过滤中使用 DataTable 类构建。您可以定义一个动态过滤器并将其应用于 DataTable 对象。动态过滤语言类似于 SQL 的一个子集,它具有 LIKE 和其他 SQL 关键字。过滤代码示例:

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'");

这样,您可以定义过滤器并将其应用于两个表,并仅比较结果集而不是每个条目。结果是一个行数组。

我在一个项目中使用它,它的 DataTable 对象包含超过 2K 个条目,性能非常好。

另一种可能性是使用 LINQ 过滤数据。您可以像这样查询 DataTable 的行:

var rows = (from DataRow dr in dt.Rows
            where dr["B"] == "2"
            select dr).ToList();

此查询返回与直接过滤相同的结果。您可以在此处再次应用相同的方法来仅检查数学结果。


如果我正确理解了您的问题,您的问题的可能解决方案可能如下所示:

// 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"]);
        }
    }
}

这种情况下的输出是:

a
 > b
 > b
d
 > d
 > d

应该将什么值写入输出取决于您 - 在找到匹配项时,您拥有所需的一切。

于 2013-11-14T17:20:09.340 回答