![](/img/trans.png)
[英]Structuring two conditional left outer joins into one query using LINQ, C#
[英]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.