![](/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.