[英]LINQ two datatables join
我陷入這個問題。 我可以通過使用foreach來解決此問題,但必須為此提供更好的解決方案。
我有兩個數據表。 第一個具有名為“ Por”的列,第二個具有名為“ FirstPor”和“ LastPor”的列。 我的目標是根據這樣的條件使用LINQ創建新的數據表。
foreach ( DataRow row in FirstDatatable.Rows )
{
foreach ( DataRow secondRow in SecondDatatable.Rows )
{
if ( row["Por"] >= secondRow["FirstPor"] && row["Por"] <= secondRow["LastPor"] )
FinalDataTable.Rows.Add(row);
}
}
我是LINQ的新手,這對我來說可能是個問題。 我可以通過Parallel.Foreach做到這一點,但我認為LINQ可能會更快。 條件很簡單。 從第一個表中獲取每個數字(“ Por”列),並從第二個表中檢查它屬於哪一行(“ Por”> =“ FirstPor” &&“ Por” <=“ LastPor”)。 我認為對於每天從事這項工作的人來說,這都很簡單。 是的,還有另一項任務。 這些列為STRING類型,因此需要在LINQ語句中進行轉換。
是的,我剛剛將我的Parallel代碼修改為LINQ / Parallel混合,看來我完成了。 我使用了James和Rahul編寫的內容,並將其放入我的代碼中。 現在,該過程需要52秒才能估計出421 000行:)更好。
public class Range
{
public int FirstPor { get; set; }
public int LastPor { get; set; }
public int PackageId { get; set; }
}
var ranges = (from r in tmpDataTable.AsEnumerable()
select new Range
{
FirstPor = Int32.Parse(r["FirstPor"] as string),
LastPor = Int32.Parse(r["LastPor"] as string),
PackageId = Int32.Parse(r["PackageId"] as string)
}).ToList();
Parallel.ForEach<DataRow>(dt.AsEnumerable(), row =>
{
int por = Int32.Parse(row["Por"].ToString());
lock (locker)
{
row["PackageId"] = ranges.First(range => por >= range.FirstPor && por <= range.LastPor).PackageId;
}
worker.ReportProgress(por);
});
(前面未經測試的代碼.....)
var newRows = FirstDatatable.Rows
.Where(row =>SecondDatatable.Rows
.Any(secondRow => row["Por"] >= secondRow["FirstPor"]
&& row["Por"] <= secondRow["LastPor"]);
FinalDataTable.Rows.AddRange(newRows);
但是,如果速度是您真正關心的問題,我的第一個建議是轉儲數據表並使用列表。 我要猜測的是SecondDatatable在很大程度上是固定的,而且概率每天變化不到一次。 因此,較少為此創建一個不錯的內存結構:
class Range
{
public int FirstPor {get; set;}
public int LastPor {get; set;}
}
var ranges = (from r in SecondDatatable.Rows
select new Range
{
FirstPor = Int32.Parse(r["FirstPor"]),
LastPor = Int32.Parse(r["LastPor"])
}).ToList();
然后我們的代碼變為:
var newRows = FirstDatatable.Rows
.Where(row =>ranges
.Any(range => row["Por"] >= range.FirstPor
&& row["Por"] <= range.LastPor).ToList();
靠它本身應該可以使速度更快。
現在,成功完成后,它將向上掃描范圍,直到找到匹配的范圍。 如果發生故障,它必須在放棄之前先掃描整個列表。 因此,我們要做的第一件事就是對范圍列表進行排序。 然后,我們只需掃描到范圍的低端,使其高於我們所尋找的值。 這樣可以將那些超出任何范圍的行的處理時間減少一半。
嘗試這個:-
DataTable FinalDataTable = (from x in dt1.AsEnumerable()
from y in dt2.AsEnumerable()
where x.Field<int>("Por") >= y.Field<int>("FirstPor")
&& x.Field<int>("Por") <= y.Field<int>("LastPor")
select x).CopyToDataTable();
這是完整的Working Fiddle ,(我已經用您的現有代碼和LINQ代碼對一些示例數據進行了測試),因為DotNet Fiddle不支持AsEnumerable,因此您可以將其復制粘貼到編輯器中並進行測試。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.