2015-12-02 43 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也可能会通知您决定使用的算法。

相关问题