Среднее из последовательных пар строк - PullRequest
0 голосов
/ 17 сентября 2018

У меня есть таблица примерно так:

id | value
---+------
1  |  10
2  |  5
3  |  11
4  |  8
5  |  9
6  |  7

Данные в этой таблице на самом деле представляют собой пары значений, из которых мне нужно взять среднее значение, которое должно привести к:

pair_id | pair_avg
--------+---------
1       | 7.5
2       | 9.5
3       | 8

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

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

Обновление

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

Таблица выглядит примерно так:

id | value
----------
1  | 10
4  | 5
6  | 11
7  | 8
10 | 9
15 | 7

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

Ответы [ 3 ]

0 голосов
/ 17 сентября 2018

Вы можете использовать функцию ceil, применяя деление на столбец от 2 до id, как в следующем операторе выбора:

with t(id,value) as
(
 select 1  ,  10  union all
 select 2  ,  5   union all
 select 3  ,  11  union all
 select 4  ,  8   union all
 select 5  ,  9   union all
 select 6  ,  7    
)
select ceil(id/2::numeric) as "ID", avg(t.value) as "pair_avg"
  from t
 group by "ID"
 order by "ID";


id | pair_avg
-------------
1  | 7.5
2  | 9.5
3  | 8
0 голосов
/ 18 сентября 2018

Если ваши данные так чисты, как кажется из вопроса: нет значений NULL, нет пробелов, пары имеют последовательные положительные числа, начиная с 1, и предполагая, что id имеет тип integer,это может быть просто:

SELECT (id+1)/2 AS pair_id, avg(value) AS pair_avg
FROM   tbl
GROUP  BY 1
ORDER  BY 1;

Целочисленное деление усекает результат и, таким образом, автоматически группирует пары таким образом.

Если ваши идентификационные номера не такие регулярные, но, по крайней мере, строго монотонно увеличивающиеся , как подсказывает ваше обновление (все еще без NULL или пропущенных значений), вы можете использовать суррогатный идентификатор, сгенерированный с помощью row_number() вместо:

SELECT id/2 AS pair_id, avg(value) AS pair_avg
FROM   <b>(SELECT row_number() OVER (ORDER BY id) + 1 AS id, value FROM tbl)</b> t
GROUP  BY 1
ORDER  BY 1;

дБ <> скрипка здесь

0 голосов
/ 17 сентября 2018

Я думаю, вы можете просто использовать group by с арифметикой:

select row_number() over (order by min(id)), min(id), max(id), avg(id)
from t
group by floor( (id - 1) / 2 );

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

...