Как в Firebird агрегировать первые N строк?

Я хотел бы сделать что-то вроде этого:

CNT=2;

//[edit]
select avg(price) from (
  select first :CNT p.Price
  from Price p
  order by p.Date desc
);

Это не работает, Firebird не допускает :cnt в качестве параметра для FIRST. Мне нужно усреднить первые самые новые цены CNT. Число 2 меняется, поэтому его нельзя жестко закодировать.

Это может быть разбито на цикл FOR SELECT и прервано при достижении счета. Хотя это лучший способ? Можно ли это сделать в одном операторе SQL?

Создание SQL в виде строки и его запуск тоже не лучший вариант. Важно, чтобы база данных скомпилировала мой оператор SQL.


person jcalfee314    schedule 23.06.2013    source источник


Ответы (2)


Вам не нужно использовать CTE, вы можете сделать это напрямую:

select avg(price) from (
  select first :cnt p.Price
  from Price p
  order by p.Date desc
);
person cincura.net    schedule 24.06.2013
comment
Firebird отклоняет это с неизвестным токеном и указывает на : перед переменной cnt. Другими словами, он не принимает переменную в качестве параметра для FIRST. - person jcalfee314; 24.06.2013
comment
Очевидно, что :variable будет работать только в PSQL. В противном случае вы не можете определить переменную. Или же вы можете использовать параметры, основанные на вашем провайдере. т.е. в .NET вы можете написать select first @cnt ... и определить параметр в FbCommand. - person cincura.net; 24.06.2013
comment
Я вижу это сейчас, в руководстве сказано, что FIRST принимает любое выражение, вычисляющее целое число. firebirdsql.org/refdocs/. Кроме того, вместо этого я должен использовать ROWS для соответствия SQL. - person jcalfee314; 24.06.2013

Вы можете использовать CTE (Common Table Expression) (см. http://www.firebirdsql.org/refdocs/langrefupd21-select.html#langrefupd21-select-cte), чтобы выбрать данные перед вычислением среднего значения. См. пример ниже:

with query1 as (
  select first 2 p.Price
  from Price p
  order by p.Date desc
)

select avg(price) from query1
person Nelson H C Nepomuceno    schedule 24.06.2013
comment
хорошая попытка, правда, мне тоже очень нравятся CTE ... однако вы жестко запрограммировали 2. я не знаю 2; это переменная. - person jcalfee314; 24.06.2013