2010-06-18 2 views
2

Жесткий вопрос SQL (кстати, я использую postgres).SQL - первая строка, вставленная каждый день за последние X дней

Мне нужна первая строка, вставленная каждый день в течение последних X дней. один из моих столбцов - это метка времени, в которой я удерживаю введенное время, а другой столбец - это идентификатор строки.

Если не удается получить первую строку, вставленную каждый день, мне по крайней мере нужен уникальный; одна строка за каждый день за последние x дней.

Любые предложения?

Благодаря

Оки

ответ

4

Вы можете попробовать что-то вроде следующего (проверено в MySQL, но я предполагаю, что это должно быть легко портировать на Postgres):

SELECT  l.id, l.timestamp, l.value 
FROM  log l 
INNER JOIN (
      SELECT MIN(timestamp) first_timestamp 
      FROM  log 
      GROUP BY DATE(timestamp) 
      ) sub_l ON (sub_l.first_timestamp = l.timestamp) 
WHERE  l.timestamp > DATE_ADD(NOW(), INTERVAL -30 DAY); 

Обратите внимание, что это предполагает, что ваши временные метки уникальны.

Test Case (в MySQL):

CREATE TABLE log (id int, timestamp datetime, value int); 

INSERT INTO log VALUES (1, '2010-06-01 02:00:00', 100); 
INSERT INTO log VALUES (2, '2010-06-01 03:00:00', 200); 
INSERT INTO log VALUES (3, '2010-06-01 04:00:00', 300); 
INSERT INTO log VALUES (4, '2010-06-02 02:00:00', 400); 
INSERT INTO log VALUES (5, '2010-06-02 03:00:00', 500); 
INSERT INTO log VALUES (6, '2010-06-03 02:00:00', 600); 
INSERT INTO log VALUES (7, '2010-06-04 02:00:00', 700); 
INSERT INTO log VALUES (8, '2010-06-04 03:00:00', 800); 
INSERT INTO log VALUES (9, '2010-06-05 05:00:00', 900); 
INSERT INTO log VALUES (10, '2010-06-05 03:00:00', 1000); 

Результат:

+------+---------------------+-------+ 
| id | timestamp   | value | 
+------+---------------------+-------+ 
| 1 | 2010-06-01 02:00:00 | 100 | 
| 4 | 2010-06-02 02:00:00 | 400 | 
| 6 | 2010-06-03 02:00:00 | 600 | 
| 7 | 2010-06-04 02:00:00 | 700 | 
| 10 | 2010-06-05 03:00:00 | 1000 | 
+------+---------------------+-------+ 
5 rows in set (0.00 sec) 
+0

Если вы добавили min (ID) в производную таблицу и условие ID в условие соединения, вы можете обойти «предполагается, что ваши временные метки являются уникальными» тоже. – potatopeelings

+0

@potatopeelings: Я не думаю, что это так просто. 'SELECT MIN (временная метка), MIN (id) FROM log GROUP BY DATE (timestamp)' в вышеприведенном тестовом примере вернет последнюю строку как '2010-06-05 03:00:00 | 9'. Если бы я должен был добавить условие ID в условие JOIN, это не соответствовало бы, потому что в таблице нет строки с timestamp = ''2010-06-05 03:00:00' И id = '9''. .. (Это, по крайней мере, в MySQL). –

+0

о да, вы правы. Виноват. Это должен быть еще один подзапрос или соединение, чтобы получить строку с самым низким ID из тех, у которых самые низкие отметки времени в день. Как вы указали - не так просто, как MIN, MIN. Сожалею! – potatopeelings

3

мистер Vassallo, вы рок-звезда.

он отлично работал. вот версия Postgres вашего SQL:

SELECT l.id, l.timestamp, l.value 
FROM log l 
INNER JOIN (
      SELECT MIN(timestamp) AS first_timestamp 
      FROM  log 
      GROUP BY DATE(timestamp) 
) sub_l ON (sub_l.first_timestamp = l.timestamp) 
WHERE  l.timestamp > NOW() - INTERVAL '30 DAY' ORDER BY l.timestamp; 

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

Я действительно ценю помощь. спасибо, что посмотрели на это.

+0

извините, это должно сказать «SELECT MIN (временная метка) AS first_timestamp» –

+0

Я рад, что это помогло. И спасибо за публикацию версии Postgres :) Я отредактировал ваш ответ, чтобы исправить часть MIN (timestamp) AS ... ', как вы предложили. –

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