2013-11-27 3 views
0

редактироватьПолучить последние данные периодической временной метки

Я понял, что мой вопрос действительно состоит из двух частей:

One of the answers ко второму вопросу использует Postgres' SELECT DISTINCT ON, что означает, что я не нужна группа вообще. Я разместил решение ниже.

У меня есть данные, которые обычно запрашиваются, чтобы получить самое последнее значение. Однако мне нужно иметь возможность воспроизвести, какие результаты были бы получены, если бы я каждый час спрашивал, возвращаясь к какой-то временной отметке.

Я не знаю с чего начать. У меня очень мало опыта работы с SQL.

CREATE TABLE history 
(
    detected timestamp with time zone NOT NULL, 
    stat integer NOT NULL 
) 

Я выбираю как:

SELECT 
detected, 
stat 

FROM history 

WHERE 
detected > '2013-11-26 20:19:58+00'::timestamp 

Очевидно, что это дает мне каждый результат, поскольку данной временной метки. Я хочу, чтобы каждый stat был ближе всего к минутам, начиная с сегодняшнего дня, до отметки времени. Ближе всего я имею в виду «меньше».

Извините, я не приложил ни малейшего усилия, чтобы приблизиться к ответу. Я так незнакома с SQL, я не знаю, с чего начать.

редактировать

Этот вопрос, How to group time by hour or by 10 minutes, кажется полезным:

SELECT timeslot, MAX(detected) 
FROM 
( 
    SELECT to_char(detected, 'YYYY-MM-DD hh24:MI') timeslot, detected 
    FROM 
    (
     SELECT detected 
     FROM history 
     where 
     detected > '2013-11-28 13:09:58+00'::timestamp 
    ) as foo 
) as foo GROUP BY timeslot 

Это дает мне самую последнюю detected метку времени на один-минутными интервалами.

Как получить stat? MAX работает на всех detected, сгруппированных по минутах, но stat недоступен.

второй редактировать

У меня есть:

timeslot;max 
"2013-11-28 14:04";"2013-11-28 14:04:05+00" 
"2013-11-28 14:17";"2013-11-28 14:17:22+00" 
"2013-11-28 14:16";"2013-11-28 14:16:40+00" 
"2013-11-28 14:13";"2013-11-28 14:13:31+00" 
"2013-11-28 14:10";"2013-11-28 14:10:02+00" 
"2013-11-28 14:09";"2013-11-28 14:09:51+00" 

Я хотел бы:

detected;stat 
"2013-11-28 14:04:05+00";123 
"2013-11-28 14:17:22+00";125 
"2013-11-28 14:16:40+00";121 
"2013-11-28 14:13:31+00";118 
"2013-11-28 14:10:02+00";119 
"2013-11-28 14:09:51+00";121 

max и detected такие же

+0

Вы пробовали MAX (обнаружено)? –

+0

@SamS Это вернет один результат, но мне нужно столько результатов, сколько минут прошло с момента времени. –

+0

Я вижу, что вам нужно. Один из способов добиться этого - скопировать данные в другую базу данных и изменить свой запрос, чтобы получить результаты, превышающие максимальную временную метку во второй таблице. Я попытаюсь сделать sqlfiddle. –

ответ

1

Я могу предложить вам это решение:

with t (tstamp, stat) as(
    values 
    ( current_timestamp,       'stat1'), 
    ( current_timestamp - interval '50' second, 'stat2'), 
    ( current_timestamp - interval '100' second, 'stat3'), 
    ( current_timestamp - interval '150' second, 'stat4'), 
    ( current_timestamp - interval '200' second, 'stat5'), 
    ( current_timestamp - interval '250' second, 'stat6') 
) 
select stat, tstamp 
from t 
where tstamp in (
    select max(tstamp) 
    from t 
    group by date_trunc('minute', tstamp) 
); 

Но это в Oracle ... может быть, это все равно поможет вам

+2

Я взял на себя смелость преобразовать это в синтаксис Postgres –

1

Хорошо еще одну попытку :)

Я попробовал это с помощью моей базы данных AdventureWorks от Microsoft. Я взял некоторые другие типы данных, но он должен работать с datetimeoffset или подобными датами.

Так что я попробовал его с петлей. Пока ваша метка меньше, чем СЕЙЧАС, выберите для меня данные между вашей меткой времени и меткой времени плюс размер интервала.С этим я получаю данные за один интервал, а затем устанавливаю метку времени и интервал, чтобы получить следующий, пока цикл while не достигнет сегодня. Может быть, это способ, если не жалко, что :)

DECLARE @today date 
DECLARE @yourTimestamp date 
DECLARE @intervalVariable date 

SET @intervalVariable = '2005-01-07' -- start at your timestamp 
SET @today = '2010-12-31' 

WHILE @intervalVariable < @today -- your Timestamp on the left side 
BEGIN 

SELECT FullDateAlternateKey FROM dbo.DimDate 
WHERE FullDateAlternateKey BETWEEN @intervalVariable AND DATEADD(dd,3, @intervalVariable) 

SET @intervalVariable = DATEADD(dd,3, @intervalVariable) -- the three is your intervale 
print 'interval' 
END 
print 'Nothing or finished' 
+0

Извините, я не очень хорошо себя объяснил. Представьте, что я пропустил опрос моей базы данных в течение 5 минут. Я хочу сказать: «Дайте мне последние 5 минут« stat », как они были бы, если бы я опросил с интервалом в 1 минуту». –

+0

Er, пожалуйста, не используйте 'BETWEEN' [с типами даты/времени/временных меток] (http://sqlblog.com/blogs/aaron_bertrand/archive/2011/10/19/what-do-between-and-the -devil-have-in-common.aspx), особенно в SQL Server. –

1

Мое решение сочетает в себе отсечение метки времени с точностью до минуты, используя to_char, и выбирая первые строки с отчетливыми минут:

SELECT DISTINCT ON (timeslot) 
to_char(detected, 'YYYY-MM-DD hh24:MI') timeslot, 
detected, 
stat 

FROM history 

ORDER BY timeslot DESC, detected DESC; 

Это было получено this answer to 'Select first row in each GROUP BY group?'.

+0

Вы уверены, что получите последнюю запись в минуту таким образом, а не только 1 случайную запись в минуту, как вы делаете сортировку после того, как вы кликнули свою дату. – Armunin

+0

@Armunin ['SELECT DISTINCT ON'] (http://www.postgresql.org/docs/current/interactive/sql-select.html#SQL-DISTINCT) использует 'ORDER BY' для выбора одной строки на каждый временной интервал. –

+0

@Armunin Я также исправил синтаксис. У меня пропали парсы вокруг «слота». –

Смежные вопросы