SQL: выберите одну запись для каждого дня, ближайшего к определенному времени - PullRequest
3 голосов
/ 21 сентября 2010

У меня есть одна таблица, в которой хранятся значения с определенным моментом времени:

CREATE TABLE values
(
    value DECIMAL,
    datetime DATETIME 
)

Может быть много значений в каждый день, также может быть только одно значение для данного дня. Теперь я хочу получить значение для каждого дня в заданный промежуток времени (например, один месяц), который является ближайшим к данному времени суток. Я хочу получать только одно значение в день, если есть записи для этого дня или нет значения, если нет записей. Моя база данных - PostgreSQL. Я застрял с этим. Я мог бы просто получить все значения во временном интервале и программно выбрать ближайшее значение для каждого дня, но это означало бы получение большого количества данных из базы данных, поскольку в один день может быть много значений.

(Update)

Чтобы сформулировать это немного более абстрактно: у меня есть данные произвольной точности (может быть одна минута, может быть два часа или два дня), и я хочу преобразовать их в фиксированную точность в один день с конкретным день.

(второе обновление)

Это запрос из принятого ответа с правильными беседами типа postgresql, при условии, что желаемое время составляет 16: 00:

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

Ответы [ 2 ]

5 голосов
/ 21 сентября 2010

Как насчет того, чтобы идти в этом направлении?

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

Я не уверен в функциях извлечения даты / времени и абс (время), поэтому вам, вероятно, придется заменить их.

2 голосов
/ 21 сентября 2010

Похоже, вам нужно решить две части:

  1. Есть ли вообще какие-либо результаты за день?

  2. Если есть, то какой ближайший?

Путем короткого замыкания процесса в части 1, если у вас нет результатов, вы сэкономите много времени на выполнение.

Следующее, что следует отметить, это то, что вам не нужно извлекать данные из базы данных, подождите, пока у вас не будет ответа, или не используйте функции PLSQL (или что-то еще), чтобы сначала обработать их на сервере. 1015 *

Если у вас есть выбор времени для проверки, вы можете использовать intervals для их сравнения. Для получения точных инструкций проверьте документы Postgres по интервалам и функциям datetime, но в основном вы минуете выбранные даты с даты, которую вы дали, и ту, с наименьшим интервалом, вы хотите.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...