简体   繁体   English

SQL:为最接近特定时间的每一天选择一条记录

[英]SQL: select one record for each day nearest to a specific time

I have one table that stores values with a point in time: 我有一个表存储一个时间点的值:

CREATE TABLE values
(
    value DECIMAL,
    datetime DATETIME 
)

There may be many values on each day, there may also be only one value for a given day. 每天可能有很多值,某一天也可能只有一个值。 Now I want to get the value for each day in a given timespan (eg one month) which is nearest to a given time of day. 现在我想获得给定时间段(例如一个月)中每天最接近给定时间的值。 I only want to get one value per day if there are records for this day or no value if there are no records. 如果有当天的记录,我只想每天获得一个值,如果没有记录,我只想获得没有值。 My database is PostgreSQL. 我的数据库是PostgreSQL。 I'm quite stuck with that. 我非常坚持这一点。 I could just get all values in the timespan and select the nearest value for each day programmatically, but that would mean to pull a huge amount of data from the database, because there can be many values on one day. 我可以在时间跨度中获取所有值并以编程方式为每一天选择最接近的值,但这意味着从数据库中提取大量数据,因为一天可能有很多值。

(Update) (更新)

To formulate it a bit more abstract: I have data of arbitrary precision (could be one minute, could be two hours or two days) and I want to convert it to a fixed precision of one day, with a specific time of day. 为了使它更具抽象性:我有任意精度的数据(可能是一分钟,可能是两小时或两天),我想将它转换为一天的固定精度,具有一天的特定时间。

(second update) (第二次更新)

This is the query from the accepted answer with correct postgresql type converstions, assuming the desired time is 16:00: 假设期望的时间是16:00,这是来自接受的答案的查询以及正确的postgresql类型转换:

SELECT datetime, value FROM values, (
  SELECT DATE(datetime) AS date, MIN(ABS(EXTRACT(EPOCH FROM TIME '16:00' - CAST(datetime AS TIME)))) AS timediff
  FROM values
  GROUP BY DATE(datetime)
  ) AS besttimes
WHERE 
CAST(values.datetime AS TIME) BETWEEN TIME '16:00' - CAST(besttimes.timediff::text || ' seconds' AS INTERVAL)
                                AND TIME '16:00' + CAST(besttimes.timediff::text || ' seconds' AS INTERVAL) 
                                AND DATE(values.datetime) = besttimes.date

How about going into this direction? 走向这个方向怎么样?

SELECT values.value, values.datetime
FROM values,
( SELECT DATE(datetime) AS date, MIN(ABS(_WANTED_TIME_ - TIME(datetime))) AS timediff
  FROM values
  GROUP BY DATE(datetime)
) AS besttimes
WHERE TIME(values.datetime) BETWEEN _WANTED_TIME_ - besttimes.timediff
                                AND _WANTED_TIME_ + besttimes.timediff
AND DATE(values.datetime) = besttimes.date

I am not sure about the date/time extracting and abs(time) functions, so you will have to replace them probably. 我不确定日期/时间提取和abs(时间)功能,所以你可能需要更换它们。

It appears you have two parts to solve: 看来你要解决两个部分:

  1. Are there any results for a day at all? 一天都有结果吗?

  2. If there are, then which is the nearest one? 如果有,那么哪个是最近的?

By shortcircuiting the process at part 1 if you have no results you'll save a lot of execution time. 如果没有结果,通过在第1部分短路过程,您将节省大量执行时间。

The next thing to note is that you don't have to pull the data from the database, wait until you have an answer or not by using PLSQL functions (or something else) to work it out on the server first. 接下来要注意的是,你不必从数据库中提取数据,等到你有答案,或者先使用PLSQL函数(或其他东西)在服务器上完成它。

Once you have a selection of times to check you can use intervals to compare them. 一旦您有选择的时间进行检查,您可以使用intervals来比较它们。 Check the Postgres docs on intervals and datetime functions for precise instructions, but basically you minus the selected dates from the date you've given and the one with the smallest interval is the one you want. 检查有关间隔和日期时间函数的Postgres文档以获得精确的说明,但基本上您减去了您给定日期的选定日期,并且间隔最小的日期是您想要的日期。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM