.net 使用LINQ从一个表和另一个表中按字段删除重复项
我必须在.net 使用LINQ从一个表和另一个表中按字段删除重复项,.net,linq,ado.net,datatable,duplicate-removal,.net,Linq,Ado.net,Datatable,Duplicate Removal,我必须在数据表中只保留数据库中当前不存在日期的记录 因此,我使用存储过程读取所有现有日期(正确吗?): 并将其加载到数据表中: var tableDate = new DataTable(); new SqlDataAdapter(command).Fill(tableDate); 现在如何从另一个表中删除所有不必要的行?我认为LINQ可能会有所帮助,但我不确定如何使用Except() 退货记录。日期除外 更新: 如果您的DataTable有键入的字段,则应如下所示: var excluded
数据表中只保留数据库中当前不存在日期的记录
因此,我使用存储过程读取所有现有日期(正确吗?):
并将其加载到数据表中
:
var tableDate = new DataTable();
new SqlDataAdapter(command).Fill(tableDate);
现在如何从另一个表中删除所有不必要的行?我认为LINQ
可能会有所帮助,但我不确定如何使用Except()
退货记录。日期除外代码>
更新:
如果您的DataTable
有键入的字段,则应如下所示:
var excluded=arbDates.Rows.OfType().Select(a=>a[0])
.Except(excDates.Rows.OfType().Select(e=>e[0])代码>
否则你可以投下它:
var excluded=arbDates.Rows.OfType()
.Select(a=>Convert.ToDateTime(a[0].ToString())
.除了(
excDates.Rows.OfType()类型
.Select(e=>Convert.ToDateTime(e[0].ToString())代码>您可以使用Except()
退货记录。日期除外代码>
更新:
如果您的DataTable
有键入的字段,则应如下所示:
var excluded=arbDates.Rows.OfType().Select(a=>a[0])
.Except(excDates.Rows.OfType().Select(e=>e[0])代码>
否则你可以投下它:
var excluded=arbDates.Rows.OfType()
.Select(a=>Convert.ToDateTime(a[0].ToString())
.除了(
excDates.Rows.OfType()类型
.Select(e=>Convert.ToDateTime(e[0].ToString())代码>我在看你的答案,你说这很有效,你只想知道如何在“单个LINQ查询”中完成。请记住,这些查询都有延迟执行,因此以下两个查询在功能上是等效的:
var q =
from d in dates
select d.Field<DateTime>("date");
return
(from r in records
where !q.Contains(r.Field<DateTime>("date"))
select r).CopyToDataTable();
(在本例中,只需将RemoveDuplicates
方法中的“date”替换为“Code”)
希望其中一个能回答你的问题。否则,我认为您必须更清楚地了解您的需求。我正在查看您的答案,您认为答案是有效的,您只想知道如何在“单个LINQ查询”中执行。请记住,这些查询都有延迟执行,因此以下两个查询在功能上是等效的:
var q =
from d in dates
select d.Field<DateTime>("date");
return
(from r in records
where !q.Contains(r.Field<DateTime>("date"))
select r).CopyToDataTable();
(在本例中,只需将RemoveDuplicates
方法中的“date”替换为“Code”)
希望其中一个能回答你的问题。否则,我认为您必须更清楚地了解您的需求。您的SQL语句看起来不错。据我所知,您正在强制转换以从午夜开始获取默认时间值。因此,被比较的另一个表中的日期也必须与该格式匹配,以便将日期与中性时间进行比较。如果没有,您仍然可以使用下面的代码,但您必须在引用tableResult
行字段的任何位置添加.Date
属性。我还使用了字段(0)
,但根据您的查询和前面的示例,您可能需要使用字段(“日期”)
不需要自定义比较器。要将LINQ查询合并到单个查询中,只需使用let
关键字,将中间结果带入查询并引用它
尝试一下:
var tableDate = new DataTable();
new SqlDataAdapter(command).Fill(tableDate);
// this is the other table that has other dates, so populate as needed
var tableResult = new DataTable();
var newTable =
(from row in tableResult.AsEnumerable()
let uniqueRows = tableResult.AsEnumerable().Select(r => r.Field<DateTime>(0))
.Except(tableDate.AsEnumerable().Select(r => r.Field<DateTime>(0)))
where uniqueRows.Contains(row.Field<DateTime>(0))
select row).CopyToDataTable();
您的SQL语句看起来不错。据我所知,您正在强制转换以从午夜开始获取默认时间值。因此,被比较的另一个表中的日期也必须与该格式匹配,以便将日期与中性时间进行比较。如果没有,您仍然可以使用下面的代码,但您必须在引用tableResult
行字段的任何位置添加.Date
属性。我还使用了字段(0)
,但根据您的查询和前面的示例,您可能需要使用字段(“日期”)
不需要自定义比较器。要将LINQ查询合并到单个查询中,只需使用let
关键字,将中间结果带入查询并引用它
尝试一下:
var tableDate = new DataTable();
new SqlDataAdapter(command).Fill(tableDate);
// this is the other table that has other dates, so populate as needed
var tableResult = new DataTable();
var newTable =
(from row in tableResult.AsEnumerable()
let uniqueRows = tableResult.AsEnumerable().Select(r => r.Field<DateTime>(0))
.Except(tableDate.AsEnumerable().Select(r => r.Field<DateTime>(0)))
where uniqueRows.Contains(row.Field<DateTime>(0))
select row).CopyToDataTable();
据我所知,您正在尝试对来自某个导入的数据进行重复数据消除。您可能不需要使用LINQ执行此操作。尽管文章标题建议使用LINQ,但您稍后会质疑LINQ是否是最好的解决方案,根据我们所知,我认为您可以使用单个Insert语句来实现这一点
首先,我建议将数据批量复制到数据库中的临时位置(如果您还没有这样做的话),如下所示:
大容量复制到临时位置的优点之一是可以添加索引等,以加快清理过程。要消除重复数据,您可以运行如下查询:
Insert DestinationData(...)
Select ...
From BulkCopyData As BCD
Where Id = (
Select Min(BCD2.[Id])
From BulkCopyData As BCD2
Where Cast(BCD2.[Date] As Date) = Cast(BCD.[Date] As Date)
)
或
这将提取它找到的第一个日期(Id最低的日期)。这显然有些武断,但为了更精确,我们需要更多地了解数据结构和要求。据我所知,您正在尝试对来自某个导入的数据进行重复数据消除。您可能不需要使用LINQ执行此操作。尽管文章标题建议使用LINQ,但您稍后会质疑LINQ是否是最好的解决方案,根据我们所知,我认为您可以使用单个Insert语句来实现这一点
首先,我建议将数据批量复制到数据库中的临时位置(如果您还没有这样做的话),如下所示:
大容量复制到临时位置的优点之一是可以添加索引等,以加快清理过程。要消除重复数据,您可以运行如下查询:
Insert DestinationData(...)
Select ...
From BulkCopyData As BCD
Where Id = (
Select Min(BCD2.[Id])
From BulkCopyData As BCD2
Where Cast(BCD2.[Date] As Date) = Cast(BCD.[Date] As Date)
)
或
这将提取它找到的第一个日期(Id最低的日期)。这显然有点武断,但为了更精确,我们需要更多地了解数据结构和需求。Hi。你能帮我写一个LINQ查询吗
var newTable = tableResult.AsEnumerable()
.Select(row => new
{
Row = row,
UniqueRows = tableResult.AsEnumerable()
.Select(r => r.Field<DateTime>(0))
.Except(tableDate.AsEnumerable().Select(r => r.Field<DateTime>(0)))
})
.Where(item => item.UniqueRows.Contains(item.Row.Field<DateTime>(0)))
.Select(item => item.Row)
.CopyToDataTable();
var commonDates = tableDate.AsEnumerable().Select(row => row.Field<DateTime>(0))
.Intersect(tableResult.AsEnumerable().Select(row => row.Field<DateTime>(0)));
for (int index = tableResult.Rows.Count - 1; index >= 0; index--)
{
if (commonDates.Contains(tableResult.Rows[index].Field<DateTime>(0)))
{
tableResult.Rows.RemoveAt(index);
}
}
Create Table TempBulkCopyData
(
Id int not null identity(1,1)
, Date DateTime2 not null
, ...
)
Insert DestinationData(...)
Select ...
From BulkCopyData As BCD
Where Id = (
Select Min(BCD2.[Id])
From BulkCopyData As BCD2
Where Cast(BCD2.[Date] As Date) = Cast(BCD.[Date] As Date)
)
Insert DestinationData(...)
Select ...
From BulkCopyData As BCD
Where Id = (
Select Min(BCD2.[Id])
From BulkCopyData As BCD2
Where DateDiff(d, BCD.[Date], BCD2.[Date]) = 0
)