2015-09-09 3 views
2

У меня следующие значения в столбце таблицы. в таблице есть два столбца. Другой столбец имеет разные даты в порядке убывания.Oracle: идентификация пиковых значений во временном ряду

3 
4 
3 
21 
4 
4 
-1 
3 
21 
-1 
4 
4 
8 
3 
3 
-1 
21 
-1 
4 

График будет enter image description here

мне нужно только пики Осроена в графике с кругами на выходе

4 
21 
21 
8 
21 
4 
+0

Нет Идентификатор столбца или подобное? – jarlh

+1

Как вы определяете порядок строк в таблице? –

+2

Если есть действительно только одна колонка, вопрос не имеет смысла. Данные в упорядоченной таблице кучи по своей сути неупорядочены. Ваш запрос неявно требует, чтобы результаты были заказаны, чтобы вы могли посмотреть на значение из «предыдущей» и «следующей» строк. Но ни с чем не приказывать, понятия «предыдущий» и «следующий» не существует. Мы можем написать запрос, который может случиться сегодня с небольшими наборами данных, но он будет прекращать работу в будущем при изменении данных. –

ответ

3

SQL Fiddle

Oracle 11g R2 Настройка схемы:

CREATE TABLE TEST (datetime, value) AS 
      SELECT DATE '2015-01-01', 3 FROM DUAL 
UNION ALL SELECT DATE '2015-01-02', 4 FROM DUAL 
UNION ALL SELECT DATE '2015-01-03', 3 FROM DUAL 
UNION ALL SELECT DATE '2015-01-04', 21 FROM DUAL 
UNION ALL SELECT DATE '2015-01-05', 4 FROM DUAL 
UNION ALL SELECT DATE '2015-01-06', 4 FROM DUAL 
UNION ALL SELECT DATE '2015-01-07', -1 FROM DUAL 
UNION ALL SELECT DATE '2015-01-08', 3 FROM DUAL 
UNION ALL SELECT DATE '2015-01-09', 21 FROM DUAL 
UNION ALL SELECT DATE '2015-01-10', -1 FROM DUAL 
UNION ALL SELECT DATE '2015-01-11', 4 FROM DUAL 
UNION ALL SELECT DATE '2015-01-12', 4 FROM DUAL 
UNION ALL SELECT DATE '2015-01-13', 8 FROM DUAL 
UNION ALL SELECT DATE '2015-01-14', 3 FROM DUAL 
UNION ALL SELECT DATE '2015-01-15', 3 FROM DUAL 
UNION ALL SELECT DATE '2015-01-16', -1 FROM DUAL 
UNION ALL SELECT DATE '2015-01-17', 21 FROM DUAL 
UNION ALL SELECT DATE '2015-01-18', -1 FROM DUAL 
UNION ALL SELECT DATE '2015-01-19', 4 FROM DUAL 

Запрос 1:

SELECT datetime, value 
FROM (
    SELECT datetime, 
     LAG(value) OVER (ORDER BY datetime) AS prv, 
     value, 
     LEAD(value) OVER (ORDER BY datetime) AS nxt 
    FROM test 
) 
WHERE (prv IS NULL OR prv < value) 
AND  (nxt IS NULL OR nxt < value) 

Results:

|     DATETIME | VALUE | 
|---------------------------|-------| 
| January, 02 2015 00:00:00 |  4 | 
| January, 04 2015 00:00:00 | 21 | 
| January, 09 2015 00:00:00 | 21 | 
| January, 13 2015 00:00:00 |  8 | 
| January, 17 2015 00:00:00 | 21 | 
| January, 19 2015 00:00:00 |  4 | 
+0

без даты и времени, null также работал –

+2

@ShravanYadav - 'заказ по null' может работать сегодня. Это может сработать завтра. Но, предполагая, что вы планируете добавлять, удалять или изменять данные, он перестанет работать. Возможно, завтра. Это может быть через неделю. Это может быть сразу после того, как вы поедете вживую. Закон Мерфи, какой он есть, вероятно, будет наименее удобным временем. –

+0

мы можем использовать rownum вместо datetime и null в порядке по условию ?? –

-1

Используя LAG функцию можно сравнить значения из различных строк. Я предполагаю, что результаты, которые вы показали, упорядочены другим столбцом с именем position.

select value 
from 
    (select value, 
      lag(value,-1) over (order by position) prev, 
      lag(value,1) over (order by position) next 
    from table) 
where value > prev 
and value > next 
+0

Я получаю ошибку [Ошибка] Выполнение (20: 7): ORA-30484: отсутствует спецификация окна для этой функции –

+0

@ Шраван Ядав: Отредактированный синтаксис должен быть правильным сейчас. – Simimmo

+0

Вы не можете иметь аналитические функции в предложении WHERE. – Ben

2

Таким образом, пик определяется как предыдущее значение и следующее значение быть меньше текущего значения, и вы можете получить предыдущий следующий с помощью LAG() и LEAD() функции.

Вам действительно нужно немного другой столбец (например, my_date), чтобы определить порядок строк, то вы можете:

select my_date, 
     value 
from (select value, 
       lag(value) over (order by my_date) lag_value, 
       lead(value) over (order by my_date) lead_value 
     from my_table) 
where value > coalesce(lag_value , value - 1) and 
     value > coalesce(lead_value, value - 1); 

Это не позволит «двойного пика», такие как:

1, 
15, 
15, 
4 

... для которого потребуется более сложная логика.

+0

зачем нужен столбец идентификатора, когда у нас есть null или rownum ?? –

+0

Поскольку порядок строк в реляционной базе данных по своей сути не определен. Когда вы вставляете строки в Oracle, нет гарантии, что они будут возвращены в том порядке, когда вы их запросите. Вы можете попробовать удалить несколько строк и вставить еще несколько, чтобы узнать, что произойдет. –

+0

О, также rownum - псевдоколонка - это только атрибут строк, возвращаемых в запросе, а не строк в самой базе данных. –

1

В Oracle 12c существует гораздо более сложный метод, который заключается в использовании соответствующего шаблону SQL.

http://docs.oracle.com/database/121/DWHSG/pattern.htm#DWHSG8966

Было бы излишним для такой ситуации, как это, но если вам нужно более сложные модели совпавшие, такие как W контурными диаграммами, то это будет стоит исследовать.

+0

правый. Он вводится только в 12c. но мы должны использовать это на практике. –

2

Просто для полноты в строке шаблон согласования, например:

WITH source_data(datetime, value) AS (
    SELECT DATE '2015-01-01', 3 FROM DUAL UNION ALL 
    SELECT DATE '2015-01-02', 4 FROM DUAL UNION ALL 
    SELECT DATE '2015-01-03', 3 FROM DUAL UNION ALL 
    SELECT DATE '2015-01-04', 21 FROM DUAL UNION ALL 
    SELECT DATE '2015-01-05', 4 FROM DUAL UNION ALL 
    SELECT DATE '2015-01-06', 4 FROM DUAL UNION ALL 
    SELECT DATE '2015-01-07', -1 FROM DUAL UNION ALL 
    SELECT DATE '2015-01-08', 3 FROM DUAL UNION ALL 
    SELECT DATE '2015-01-09', 21 FROM DUAL UNION ALL 
    SELECT DATE '2015-01-10', -1 FROM DUAL UNION ALL 
    SELECT DATE '2015-01-11', 4 FROM DUAL UNION ALL 
    SELECT DATE '2015-01-12', 4 FROM DUAL UNION ALL 
    SELECT DATE '2015-01-13', 8 FROM DUAL UNION ALL 
    SELECT DATE '2015-01-14', 3 FROM DUAL UNION ALL 
    SELECT DATE '2015-01-15', 3 FROM DUAL UNION ALL 
    SELECT DATE '2015-01-16', -1 FROM DUAL UNION ALL 
    SELECT DATE '2015-01-17', 21 FROM DUAL UNION ALL 
    SELECT DATE '2015-01-18', -1 FROM DUAL UNION ALL 
    SELECT DATE '2015-01-19', 4 FROM DUAL 
) 
SELECT * 
FROM 
    source_data MATCH_RECOGNIZE (
     ORDER BY datetime 
     MEASURES 
      LAST(UP.datetime) AS datetime, 
      LAST(UP.value) AS value 
    ONE ROW PER MATCH 
    PATTERN ((UP DOWN) | UP$) 
    DEFINE 
     DOWN AS DOWN.value < PREV(DOWN.value), 
     UP AS UP.value > PREV(UP.value) 
    ) 
ORDER BY 
    datetime 
+0

Это пропустит пик в первой строке, если значение в первой строке больше, чем во второй строке. Чтобы исправить это, определение 'UP' может быть расширено, чтобы включить' или PREV (значение) null. – mathguy

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