簡體   English   中英

C# Linq 查詢將兩個表合並為一個?

[英]C# Linq query which joins two tables in to one?

我的代碼需要幫助。 我有兩個具有相同結構的數據表:列和列類型。 不同之處在於某些表格單元格可以為空或填充。 問題是我需要將它們合二為一,如果 null 值將出現在其中一個表中,則將它們替換為現有值,而不創建重復記錄。

結構 dt1 EmployeeID|公司|司機姓名|經理|

結構 dt2 EmployeeID|公司|司機姓名|經理|

示例數據:

結構 dt1

EmployeeID|Company|Driver name|Manager  |Manager Email     |HR Admin
000000001 |VW     |John       |Veronica |null              |Lucas
000000002 |Audi   |Monica     |John     |john@john.com     |null
000000003 |Fiat   |Thomas     |Michael  |null              |null

結構 dt1

EmployeeID|Company|Driver name|Manager  |Manager Email     |HR Admin
000000001 |VW     |John       |null     |Veronica@john.com |null
000000002 |null   |Monica     |John     |null              |Martha
000000003 |null   |null       |Michael  |Michael@john.com  |Lucas

預期結果應該是:

EmployeeID|Company|Driver name|Manager  |Manager Email     |HR Admin
000000001 |VW     |John       |Veronica |Veronica@john.com |Lucas
000000002 |Audi   |Monica     |John     |john@john.com     |Martha
000000003 |Fiat   |Thomas     |Michael  |Michael@john.com  |Lucas

我在谷歌上搜索並附帶了這段代碼,但它返回了錯誤的結果。 我不熟悉 LINQ。 謝謝您的支持!

try
            {

ErrorMessage = "";
                CollectionOut = new DataTable();
                DataTable dt1 = new DataTable();
                DataTable dt2 = new DataTable();
                            DataTable dt3 = new DataTable();
                            dt3.Columns.Add("EmployeeID", typeof(string));
                            dt3.Columns.Add("Company", typeof(string));
                            dt3.Columns.Add("Driver name", typeof(string));
                            dt3.Columns.Add("Manager", typeof(string));
                            dt3.Columns.Add("Manager Email", typeof(string));
                            dt3.Columns.Add("HR Admin", typeof(string));

                dt3 = (from a in dt1.AsEnumerable()
                       join b in dt2.AsEnumerable() on a.Field<string>("EmployeeID") equals b.Field<string>("EmployeeID")
                       select dt3.LoadDataRow(new object[]
                       {
                            a.Field<string>("EmployeeID"),
                            b.Field<string>("Company"),
                            b.Field<string>("Driver name"),
                            b.Field<string>("Manager"),
                            b.Field<string>("Manager Email"),
                            b.Field<string>("HR Admin"),
                       }, false))
                    .CopyToDataTable();
CollectionOut = dt3;
            }
                catch (Exception ex)
            {
                ErrorMessage = ex.Message.ToString();

            }

你的代碼幾乎可以做你想做的事。 你只需要使用

a.Field<string>("EmployeeID"),
a.Field<string>("Company") ?? b.Field<string>("Company"),
a.Field<string>("Driver name") ?? b.Field<string>("Driver name"),
a.Field<string>("Manager") ?? b.Field<string>("Manager"),
a.Field<string>("Manager Email") ?? b.Field<string>("Manager Email"),
a.Field<string>("HR Admin") ?? b.Field<string>("HR Admin"),

代替

a.Field<string>("EmployeeID"),
b.Field<string>("Company"),
b.Field<string>("Driver name"),
b.Field<string>("Manager"),
b.Field<string>("Manager Email"),
b.Field<string>("HR Admin"),

在您的示例中,您將第一個表中的 EmployeeID 和第二個表中的所有其他列設置為結果表。 但是,如果要填充不包括空值的結果表,則必須嘗試從第一個表中設置值,如果它們是 null,則從第二個表中設置值。 (有關更多信息,您可以閱讀?? 運算符

您還可以根據自己的選擇從任何源表中填充結果表,甚至可以使用不同的列作為結果表中 1 列的源。 這是一個例子。

        var ErrorMessage = "";
        try
        {
            var CollectionOut = new DataTable();

            //Structure of first datatable
            DataTable dt1 = new DataTable();
            dt1.Columns.Add("EmployeeID", typeof(string));
            dt1.Columns.Add("Company", typeof(string));
            //dt1.Columns.Add("Driver name", typeof(string));
            //dt1.Columns.Add("Manager", typeof(string));
            dt1.Columns.Add("Manager Email", typeof(string));
            dt1.Columns.Add("HR Admin Name1", typeof(string));

            //Structure of second databable
            DataTable dt2 = new DataTable();
            dt2.Columns.Add("EmployeeID", typeof(string));
            dt2.Columns.Add("Company", typeof(string));
            dt2.Columns.Add("Driver name", typeof(string));
            dt2.Columns.Add("Manager", typeof(string));
            //dt2.Columns.Add("Manager Email", typeof(string));
            dt2.Columns.Add("HR Admin Name2", typeof(string));

            //Structure of result datatable
            DataTable dt3 = new DataTable();
            dt3.Columns.Add("EmployeeID", typeof(string));
            dt3.Columns.Add("Company", typeof(string));
            dt3.Columns.Add("Driver name", typeof(string));
            dt3.Columns.Add("Manager", typeof(string));
            dt3.Columns.Add("Manager Email", typeof(string));
            dt3.Columns.Add("HR Admin", typeof(string));

            //Data for example
            dt1.Rows.Add("1", "1", "1", "1", "1", "1");
            dt1.Rows.Add("2", "1", "1", null, "1", "1");
            dt1.Rows.Add("3", "1", "1", "1", null, "1");
            dt2.Rows.Add("1", "1", "1", null, "1", null);
            dt2.Rows.Add("2", "1", "1", "2", "1", "1");
            dt2.Rows.Add("3", "1", "1", "1", "2", "1");

            //Fill result table
            dt3 = (from a in dt1.AsEnumerable()
                         join b in dt2.AsEnumerable() on a.Field<string>("EmployeeID") equals b.Field<string>("EmployeeID") //you join table on your EmployerID here
                         select dt3.LoadDataRow(new object[]
                         {
                             a.Field<string>("EmployeeID"), //result gets EmployeeID from first table
                             a.Field<string>("Company") ?? b.Field<string>("Company"),  //result gets Company from first table, but if it is null then it gets Company from second table
                             b.Field<string>("Driver name"), //result gets Driver name from second table (because we don't have Driver name in first table
                             a.Field<string>("Manager") ?? b.Field<string>("Manager"), //same
                             a.Field<string>("Manager Email"), //result gets Manager Email from first table (because we don't have Manager Email in second table)
                             a.Field<string>("HR Admin Name1") ?? b.Field<string>("HR Admin Name2"), //fil HR Admin column from HR Admin Name1 in 1st table or, if null, from HR Admin Name2 in 2nd table
                         }, false))
                    .CopyToDataTable();
            CollectionOut = dt3;
        }
        catch (Exception ex)
        {
            ErrorMessage = ex.Message.ToString();
        }

如果dt1中的記錄不在dt2中(反之亦然),則一個連接是不夠的。 你必須做一些像完全外連接這樣的事情。 我用arrays編寫示例,但您可以輕松地將它們替換為DataTable

例子:

\\Helper test class

public class Test
{
   public int Id { get; set; }
   public string A { get; set; }
   public string B { get; set; }
}
var a = new[]
{
    new Test{ Id = 1, A = "AAAAA", B = null },
    new Test{ Id = 2, A = null , B = "BBBB"}
};
var b = new[]
{
    new Test{ Id = 1,  A = null , B = "BBBB" },
    new Test{ Id = 2, A = "AAAAA", B = null },
    new Test{ Id = 3, A = "AAAAA", B = "BBBBB" },
};
var leftOuterJoin =
    from first in a
    join last in b on first.Id equals last.Id into temp
    from last in temp.DefaultIfEmpty()
    select new
    {
        first.Id,
        A = !string.IsNullOrEmpty(first.A) ? first.A : last?.A,
        B = !string.IsNullOrEmpty(first.B) ? first.B : last?.B,
    };

var rightOuterJoin =
    from last in b
    join first in a on last.Id equals first.Id into temp
    from first in temp.DefaultIfEmpty()
    select new
    {
        last.Id,
        A = !string.IsNullOrEmpty(last.A) ? last.A : first?.A,
        B = !string.IsNullOrEmpty(last.B) ? last.B : first?.B,
    };

//fullOuterJoin is result
var fullOuterJoin = leftOuterJoin.Union(rightOuterJoin);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM