我有一个名为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。
...
12/02/2015 14:57:59.768
12/02/2015 14:59:48.089
12/02/2015 15:00:59.453
12/02/2015 15:02:12.145
12/02/2015 15:10:35.789
12/02/2015 15:16:01.376
.......
我尝试使用
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)
从广义上讲,您希望获得增量时间的绝对值(虽然不要尝试克里斯的代码,但您不能在TimeSpan上调用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.
答案 1 :(得分:0)
您希望从目标时间中获取数据库中时间戳的绝对差值,并采用最小差异。
var result = data.Min(r = Math.Abs(r.Timestamp - targettime));
答案 2 :(得分: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)
使用LINQ的.Aggregate()
方法可以实现类似的东西(以及IMO,同样丑陋)。遗憾的是,LINQ并没有为您提供干净,高效,开箱即用的方式来满足您的需求,但是,如果您有兴趣,可以查看一个库,MoreLINQ,提供MinBy()
扩展方法。即使您选择不使用它,source code也可以通知您决定使用的算法。