Создание нескольких максимальных и минимальных значений с помощью SQL Query - PullRequest
1 голос
/ 22 марта 2011

Я разочарован любопытным ограничением SQL - его очевидной неспособностью связывать одну запись с другой вне агрегатных функций.Моя проблема обобщена таким образом.У меня есть таблица, уже отсортированы.Мне нужно найти его максимальные значения (обратите внимание на множественное число!) И минимальные значения.Нет, я не ищу ни одного максимума или единственного минимума.Более конкретно я пытаюсь сгенерировать список локальных пиков числовой последовательности.Примерное описание алгоритма для его генерации:

WHILE NOT END_OF_TABLE
 IF RECORD != FIRST_RECORD AND RECORD != LAST_RECORD THEN
  IF ((RECORD(Field)<RECORD_PREVIOUS(Field) AND RECORD(Field)<RECORD_NEXT(Field)) OR
      RECORD(Field)>RECORD_PREVIOUS(Field) AND RECORD(Field)>RECORD_NEXT(Field)) THEN
     ADD_RESULT RECORD
  END IF
 END IF
END WHILE

См. Проблему?Мне нужно сделать запрос, который данная запись должна сравнить со значениями предыдущей и следующей записи.Можно ли это сделать даже в стандартном SQL?

Ответы [ 4 ]

2 голосов
/ 22 марта 2011

Вы должны самостоятельно присоединиться дважды и сгенерировать число без пробелов:

В T-SQL:

WITH ordered AS (
    SELECT ROW_NUMBER() OVER (ORDER BY your_sort_order) AS RowNumber
           ,* -- other columns here
)
SELECT *
FROM ordered
LEFT JOIN ordered AS prev
    ON prev.RowNumber = ordered.RowNumber - 1
LEFT JOIN ordered AS next
    ON next.RowNumber = ordered.RowNumber + 1
WHERE -- here you put in your local min/local max and end-point handling logic - end points will have NULL in next/prev
2 голосов
/ 22 марта 2011

Ваше разочарование разделяют многие; в то время как SQL отлично подходит для работы с общими наборами, он ужасно несовершенен, когда пытается работать с проблемами, специфичными для упорядоченных наборов (будь то физически упорядоченный в таблице или неявный или явный логический порядок не имеет значения). Есть некоторые вещи, которые могут помочь (например, функции rank() и row_number()), но решения могут отличаться в зависимости от СУБД.

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

1 голос
/ 22 марта 2011
SELECT
  current.RowID,
  current.Value,
  CASE WHEN
    (
     (current.Value < COALESCE(previous.Value,   current.Value + 1))
     AND
     (current.Value < COALESCE(subsequent.Value, current.Value + 1))
    )
  THEN
    'Minima'
  ELSE
    'Maxima'
  END
FROM
  myTable  current
LEFT JOIN
  myTable  previous
    ON previous.RowID = (SELECT MAX(RowID) FROM myTable WHERE RowID < current.ROWID)
LEFT JOIN
  myTable  subsequent
    ON subsequent.RowID = (SELECT MIN(RowID) FROM myTable WHERE RowID > current.ROWID)
WHERE
  (
   (current.Value < COALESCE(previous.Value,   current.Value + 1))
   AND
   (current.Value < COALESCE(subsequent.Value, current.Value + 1))
  )
  OR
  (
   (current.Value > COALESCE(previous.Value,   current.Value - 1))
   AND
   (current.Value > COALESCE(subsequent.Value, current.Value - 1))
  )

Примечание: Логика <и> скопирована с вас, но не обслуживает локальные максимумы / минимумы, которые равны для одной или нескольких последовательных записей.

Примечание: Я создал вымышленный RowID для объединения записей по порядку, важно лишь, чтобы объединения получали "предыдущие" и "последующие" записи.

Примечание: Операторы LEFT JOINs и COALESCE приводят к тому, что первое и последнее значения всегда считаются максимумами или минимумами.

1 голос
/ 22 марта 2011

Да.Вам необходимо самостоятельное объединение, но без схемы базы данных сложно определиться с решением.

В частности, мне интересно, что вы упомянули об «заказе», но я собираюсь предположить, что для этого можно использовать поле «ID».

(О, и я использую синтаксис старой школы, потому что я динозавр).

select *
from   myTable   main,
       myTable   previous,
       myTable   next
where  previous.id  = main.id - 1
and    next.id      = main.id + 1
and    previous.record > main.record
and    next.record     < main.record

(Я думаю, что я правильно истолковал ваше требование в большей/ меньше, чем пункты, но приспособиться по вкусу).

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