SQLite查询以获取最接近的日期时间

时间:2015-06-24 16:06:38

标签: sql sqlite datetime

我正在尝试编写一个SQLite语句,以便从用户输入(来自WPF日期选择器)获取最接近的日期时间。我有一个表IRquote(rateId,quoteDateAndTime,quoteValue)。

例如,如果用户输入10/01/2000并且数据库仅在08/01 / 2000,07 / 01/2000和14/01/2000存储了修复,则它将返回08/01/2000,是2000年10月1日以来最接近的日期。

当然,我希望它不仅适用于日期,也适合时间。

我尝试使用此查询,但它返回的日期最晚的行,而不是最接近的行:

SELECT quoteValue FROM IRquote 
WHERE rateId = '" + pRefIndexTicker + "'
ORDER BY abs(datetime(quoteDateAndTime) - datetime('" + DateTimeSQLite(pFixingDate) + "')) ASC
LIMIT 1;

请注意,我有一个函数DateTimeSQLite,可以将用户输入转换为正确的格式。

我不明白为什么这不起作用。 我怎么能这样做?谢谢你的帮助

3 个答案:

答案 0 :(得分:6)

要获得最接近的日期,您需要使用 strftime('%s', datetime) SQLite函数。

使用this示例/演示,您将获得与指定日期最接近的日期 请注意,日期2015-06-25 10:00:00是用户选择的输入日期时间。

select t.ID, t.Price, t.PriceDate,
       abs(strftime('%s','2015-06-25 10:00:00') - strftime('%s', t.PriceDate)) as 'ClosestDate'
  from Test t
 order by abs(strftime('%s','2015-06-25 10:00:00') - strftime('%s', PriceDate))
 limit 1;

SQL解释:
我们使用strftime('%s') - strftime('%s')来计算两个日期之间的差异(以秒为单位)(注意:它必须是'%s',不是'% S&#39)。由于这可能是正面的,也可能是正面的,我们还需要使用abs函数使其全部为正,以确保我们的order by和后续limit 1部分正确无误。

答案 1 :(得分:3)

如果表很大,并且datetime列上有索引,这将使用索引获取最接近的2行(在提供的值之上和之下)并且效率更高:

select * 
from
  ( select * 
    from 
    ( select t.ID, t.Price, t.PriceDate
      from Test t
      where t.PriceDate <= datetime('2015-06-23 10:00:00') 
      order by t.PriceDate desc
      limit 1
    ) d
  union all
    select * from
    ( select t.ID, t.Price, t.PriceDate
      from Test t
      where t.PriceDate > datetime('2015-06-23 10:00:00') 
      order by t.PriceDate asc
      limit 1
    ) a
  ) x
order by abs(julianday('2015-06-23 10:00:00') - julianday(PriceDate))
limit 1 ;

经过SQLfiddle测试。

答案 2 :(得分:1)

另一个有用的解决方案是使用 BETWEEN 运算符,如果您可以确定时间/日期查询的上限和下限。我最近在此link中遇到了此解决方案。这就是我在名为t的时间列上用于应用程序的内容(更改日期列和日期函数的代码并不困难):

select *
from myTable 
where t BETWEEN '09:35:00' and '09:45:00' 
order by ABS(strftime('%s',t) -  strftime('%s','09:40:00')) asc 
limit 1

此外,我必须更正对以上帖子的评论。我尝试了对@ BerndLinde,@ypercubeᵀᴹ和我提出的这3种方法的速度进行简单检查。我的PC中大约有500个表,每个中型硬件有150行。结果是:

  1. 解决方案1(使用strftime)大约需要12秒。
  2. 将列t的索引添加到解决方案1中可将速度提高约30%,耗时约8秒。使用time(t)索引并没有任何改善。
  3. 与解决方案1相比,解决方案2的速度提高了约30%,耗时约8秒
  4. 最后,解决方案3改进了约50%,耗时约5.5秒。 t列的索引增加了一点改进,大约需要4.8秒。时间索引(t)在此解决方案中不起作用。

注意:我是一个简单的程序员,这是.NET代码中的简单测试。真正的性能测试必须考虑更多专业方面,而我对此并不了解。在查询和读取数据库之后,我的代码中也进行了一些计算。另外,正如@ypercubeᵀᴹ指出的那样,对于大量数据,此结果也无效。