2015-12-02 217 views
0

我有一個名爲Timestamp和其他列的數據表。我試圖找到時間戳最接近給定時間的那些行。例如,有一些行具有不同的時間戳。我如何找到最接近12/02/2015 15:00:00,12/02/2015 15:15:00等的行。在以下示例中,帶有時間戳的行12/02/2015 14:59 :48.089和12/02/2015 15:16:01.376分別是給定時間12/02/2015 15:00:00和12/02/2015 15:15:00的最封閉行。在數據表中找到最接近給定時間的時間戳的行

....

2015年12月2日14:57:59.768

2015年12月2日14:59:48.089

2015年12月2日15:00:59.453

2015年12月2日15:02:12.145

2015年12月2日15:10:3​​5.789

2015年12月2日15:16:01.3 76

.......

我試圖用

DataRow[] drRows = dtMyRecords.Select("MIN(Timestamp-#12/02/2015 15:00:00#)"); 

object obj = dtStationRecords.Compute("MIN(Timestamp-'12/02/2015 15:15:00')", null); 

找到它。但他們不工作。你能給解決方案嗎?

+0

列的類型是什麼? –

+1

@harmony這裏是一個很好的鏈接,看看http://www.csharp-examples.net/dataview-rowfilter/ – MethodMan

回答

0

你想從你的目標時間的數據庫中的時間戳之間的絕對差異,並採取最小的差異。

var result = data.Min(r = Math.Abs(r.Timestamp - targettime)); 
0

廣義上說,你想要得到的時間增量的絕對值(雖然不嘗試克里斯的代碼,你不能叫一個時間跨度Math.Abs​​())。您可能必須先解析輸入,例如使用DateTime.Parse()。

下面是一些代碼來選擇最接近的一個。它使用模擬數據(dates),因爲我不知道你的DataSet是什麼樣的。

string[] dates = new[] { "12/02/2015 14:57:59.768", "12/02/2015 14:59:48.089" }; 
DateTime target = DateTime.Parse("12/02/2015 14:58:00"); 
var closest = dates 
    .Select(date => new { 
     date, distance = Math.Abs(DateTime.Parse(date)Ticks - target.Ticks)}) 
    .OrderBy(dt => dt.distance) 
    .First().date; 

結果:

12/02/2015 14:57:59.768

然而,而非實施這種自己,爲什麼不爲你的數據庫做呢?除非您重複使用數據,否則這將導致更小的交易和更快的查找。

DECLARE @target DateTime = '2015-05-05 12:15:00' --your query input 
SELECT TOP 1 Timestamp 
FROM YourTable 
ORDER BY ABS(DATEDIFF(SS, Timestamp, @target)) 
-- "SS" above means second-level precision. 
0

我懷疑你正在尋找的東西是這樣的:

DateTime target = new DateTime(2015,12,2,15,0,0); 

var closest = dtMyRecords.AsEnumerable() 
    .Select(drRow => drRow.Field<DateTime>("Timestamp")) 
    .OrderBy(d => Math.Abs(d.Ticks - target.Ticks)) 
    .First(); 

這將正常工作,如果這不是一個性能關鍵的應用程序,但使用.OrderBy()麻煩的是你真的不需要重新排列元素。您需要枚舉一次您的DataTable並記錄最近的項目。

像下面的算法是有點難看,但有點更高效計算:

DateTime target = new DateTime(2015,12,2,15,0,0); 

DateTime closest=DateTime.MinValue; 
long closestTicks=long.MaxValue; 

foreach(var d in dtMyRecords.AsEnumerable().Select(drRow=>drRow.Field<DateTime>("Timestamp"))) 
{ 
    long currentTicks = Math.Abs(d.Ticks - target.Ticks); 
    if(currentTicks >= closestTicks) continue; 
    closestTicks = currentTicks; 
    closest = d; 
} 

// "closest" will now hold the closest date (or defaults if the sequence contains no elements) 

類似的東西(和,IMO,類似地難看)可以與LINQ的.Aggregate()方法來完成。不幸的是,LINQ並沒有給你一個乾淨,高效的開箱即用的方式來做你需要的東西,但是,如果你有興趣,有一個庫可以查看,MoreLINQ,它提供了一個MinBy()擴展方法。即使您選擇不使用它,source code也可能會通知您決定使用的算法。

相關問題