LINUX.ORG.RU

plsql


0

0

Что-то подвис: надо выбрать все записи по порядку, сумма значений которых не превышает определённую величину.

TREASURY=# select * from ocp;
 id | bcid | scid | price |  amount  |   tdate    |   vdate
----+------+------+-------+----------+------------+-----------
  1 |    1 |    3 | 28.05 |  1000000 | 2008-12-08 | 2008-12-08
  2 |    3 |    1 | 28.23 | 28230000 | 2008-12-08 | 2008-12-08
  3 |    1 |    3 | 28.06 |   210000 | 2008-12-08 | 2008-12-08
  4 |    1 |    3 | 28.07 |   150000 | 2008-12-08 | 2008-12-08
(4 rows)

Как отсюда достать последние 2 записи, при определённой величине в 360000?

И ещё, postgres поддерживает внутризапросные переменные? Если, например, я захочу накапливать сумму значений определённых полей в запросе, типа: select @a := @a + amount ?

★★★★★

Я тоже подвис от самого факта вопроса :)

select * from ocp where amount < 360000;

не? :)

> И ещё, postgres поддерживает внутризапросные переменные? Если, например, я захочу накапливать сумму значений определённых полей в запросе, типа: select @a := @a + amount ?


ну...
select sum(amount) as summary_amount from ocp where amount < 360000;

?

Slavaz ★★★★★
()

Лучше приведи кусок процедуры, в которой пытаешься работать с таблицей.
Там видно будет, что нужно сделать.

Slavaz ★★★★★
()

Не сделать это эффективно, увы. Напиши SP, которая откроет курсор и будет читать оттуда пока сумма не достигнет заданного порогового значения. В этом случае придется надеятся что оно будет достигнуто быстро, потому что если оно будет достигнуто не сразу, то может получиться весьма неэффективно.

gods-little-toy ★★★
()
Ответ на: комментарий от Slavaz

> select * from ocp where amount < 360000;

Ты меня не понял. Вывести нужно только те записи _сумма значений_ которых не превышает 360000. Т.е. сквозная сумма. В конкретном примере - 2 последние строчки, так как их сумма аккурат равна 360000.

В твоем же запросе выведутся _все_ записи из таблицы _значения_ которых меньше 360000.

> > И ещё, postgres поддерживает внутризапросные переменные? Если, например, я захочу накапливать сумму значений определённых полей в запросе, типа: select @a := @a + amount ?


>ну...

>select sum(amount) as summary_amount from ocp where amount < 360000;


Не то опять. Мне не надо аггрегировать, надо накапливать и выводить в общем порядке.

Anoxemian ★★★★★
() автор топика
Ответ на: комментарий от gods-little-toy

> Не сделать это эффективно, увы. Напиши SP, которая откроет курсор и будет читать оттуда пока сумма не достигнет заданного порогового значения. В этом случае придется надеятся что оно будет достигнуто быстро, потому что если оно будет достигнуто не сразу, то может получиться весьма неэффективно.

Ужас какой. Это легко реализуется в mysql и, насколько я помню, даже в ms access. Не думал что тут можно так забуксовать на простейшей задаче.

Т.е. я так понимаю штатных средств для подсчёта средневзвешенной величины и внутренних переменных впринципе не существует?

Anoxemian ★★★★★
() автор топика

Хм... а вот так тоже нельзя?

select 
    ocp.id as VAL1, 
    *, 
    (select sum(amount) from ocp where ocp.id < VAL1) 
from 
    ocp 
where 
    bcid=1 or scid=1;

Как в таких случаях передавать значение?

Anoxemian ★★★★★
() автор топика
Ответ на: комментарий от Anoxemian

не совсем понимаю как этот запрос даст искомое, у него же в where никаких ограничений по суммам.

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

select * from t1 OUTER

where (select sum(amount) from t1 where amount < OUTER.amount) < $NEEDED_SUM

проблема в том, что это не соптимизируется (постгресом/mysql'eм/иже с ними - точно) и будет медленнее чем решения на курсорах или @@variable.

gods-little-toy ★★★
()

я как-то поднимал уже беседу на предмет поддержки аналитики в опенсорсных СУБД. Внятного решения из коробки нет. Зато слюней у красноглазых хоть отбавляй. К чему я собственно... вот наглядный пример... нет возможности применить сумму с накоплением.

В оракле это делается одной строкой, так оно и логично, ведь операция "однопроходная".

select sum(f_money) over (order by f_date ) from my_big_bank

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

Deleted
()
Ответ на: комментарий от Deleted

> Внятного решения из коробки нет. Зато слюней у красноглазых хоть отбавляй.

Ну тут надо включать мозг и, уповая на то, что sql - тьюринг-полный, ломать мозг над реализацией необходимых вещей.

Anoxemian ★★★★★
() автор топика
Ответ на: комментарий от Anoxemian

Мозг поломан, но эффект достигнут:

select 
    t2.id,
    (select sum(usd.amount2) from usd where usd.id <= t2.id) as amount3
from 
    (
    SELECT 
        t1.id, 
        t1.bcid, 
        t1.scid, 
        t1.price, 
        t1.amount, 
        t1.tdate, 
        t1.vdate, 
        ( 
        SELECT 
            CASE
                WHEN ocp.bcid = 1 THEN ocp.amount
                WHEN ocp.scid = 1 THEN (- ocp.amount) / ocp.price
            END
        FROM 
            ocp
        WHERE 
            ocp.id = t1.id
        ) AS amount2
    FROM 
        ocp as t1
    WHERE 
        t1.bcid = 1 OR 
        t1.scid = 1
    ) as t2
WHERE 
    t2.bcid = 1 OR 
    t2.scid = 1
GROUP BY t2.id
ORDER BY t2.id

Смысл в том, что величина amount3 - сквозная накопительная сумма.

Anoxemian ★★★★★
() автор топика
Ответ на: комментарий от Anoxemian

А где у тебя в запросе условие про 360000?

anonymous
()
Ответ на: комментарий от Deleted

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

Их самому написать на C проще пареной репы.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.