PostgreSQL и последовательные данные - PullRequest
5 голосов
/ 05 октября 2009

У меня есть набор данных, который содержит:

Table { date itemName }

Дата по большей части является последовательной. Дубликатов даты нет [так как это первичный ключ].

Вопрос разбит на несколько частей (все относительно использования SQL):

  1. Можно ли найти пробелы в ряду дат, указанных в таблице? Например: Даты 1/2/09-1/3/09 отсутствуют
  2. Можно ли найти разделы дат, отсутствующие в таблице, у которых диапазон больше n (это число определяется во время выполнения)? Например: для n = 2 Даты 1/2/09-1/3/09 не возвращаются, а Даты 5/6/09-6/1/09.

Ответы [ 3 ]

10 голосов
/ 05 октября 2009

Если вы можете использовать PostgreSQL 8.4, тогда оконные функции помогут:

SELECT *
    FROM (SELECT itemName, date, date - lag(date) OVER w AS gap
              FROM someTable WINDOW w AS (ORDER BY date)
         ) AS pairs
    WHERE pairs.gap > '1 day'::interval;
1 голос
/ 05 октября 2009

После некоторого тестирования я предложил следующий оператор SQL:

SELECT date, itemName
  FROM "Table" as t1
  WHERE NOT EXISTS (
     SELECT date 
     FROM "Table" as t2 
     WHERE t2.date = (t1.date - INTERVAL '1 day')
  )
  ORDER BY date
  OFFSET 1  -- this will skip the first element

Это даст вам все строки, которые не имеют прямого преемника.

Если вы измените утверждение на:

SELECT date, itemName
  FROM "Table" as t1
  WHERE NOT EXISTS (
    SELECT date 
    FROM "Table" as t2 
    WHERE (t2.date >= (t1.date - INTERVAL '2 day'))
    AND (t2.date < t1.date)
  )
  ORDER BY date
  OFFSET 1

вы можете использовать длину ИНТЕРВАЛА в предложении WHERE подвыбора для фильтрации по промежуткам, по крайней мере, такого размера.

Надеюсь, это поможет.

1 голос
/ 05 октября 2009

Просто создайте функцию в plsql или в клиенте, которая будет проверять все даты. Как этот псевдокод:

date checked_date = 2000-01-01;
int unchecked_section = 0;
while ( checked_date <= today() ) {
  if (! sql(select itemName from Table where itemName=checked_date)) {
    unchecked_section++;
  } else {
    if ( unchecked_section>=n ) {
      print checked_date-unchecked_section, checked_date
    }
    unchecked_section = 0;
  }
  checked_date++;
}
if ( unchecked_section ) {
  print checked_date-unchecked_section, checked_date
}

Это не должно быть очень быстро, поскольку это только обслуживание. Проверять не так много дат - всего 365 в год.

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