-
две таблицы T_MINUS (расход) DT date(datetime) not null SUMMA number(int) not null
T_PLUS (доход) DT date(datetime) not null SUMMA number(int) not null
требуется вывести те расходы, которые не покрыты доходом
например в T_MINUS (расход) 01.01.2000 100 02.01.2000 100 03.01.2000 100 04.01.2000 100 05.01.2000 100
в T_PLUS (доход) 03.01.2000 200 04.01.2000 200
тогда ответ должен быть 05.01.2000 100
т.к. Получается, что 5 дней тратилось по 100 денег, в третий день погасились траты первых 2х дней, в 4й еще 2х дней, апятый день остался не погашен.
-
даже проще. Уберем T_PLUS Есть только T_MINUS и число. Надо взять первые строки по дате, сумма которых по деньгам не превышает заданное число.
через функцию написал уже , где (курсором) вычитается из параметра, пока разность >=0 но на приличных объемах это работает долго
-
v_ID := 0; if p_SUMM = 0 then -- считаем сколько всего оплатили select nvl(sum(P.SUMM),0) + nvl(sum(P.PENISUMM),0) into v_MMM from main.t_payments P join main.t_pay_cross_vnd PV on PV.PAYMENT_ID = P.PAYMENT_ID where P.USER_ID = p_USER_ID and PV.VNDR_ID = 3164832784; --АУДИОТЕЛЕ end if; for C in -- все услуги отнимаются от суммы, пока не будет <0 ( select OS.OTH_SVC_ID, OS.OPERSUMM from main.t_other_svc OS join main.t_svc_ref SR on SR.SVC_ID = OS.SVC_ID where SR.Name like '%АУДИОТЕЛЕ%' and OS.User_Id = p_USER_ID order by OS.OTH_SVC_ID ) loop if v_MMM - C.OPERSUMM < 0 then begin v_ID := C.OTH_SVC_ID; Exit; end; else begin v_MMM := v_MMM - C.OPERSUMM; end; end if; end loop; return(v_ID);
и как то так select OS.OTH_SVC_ID, OS.OPERSUMM, OS.Svc_Date, os.info from OW_TMP_AUD A join main.t_other_svc OS on OS.USER_ID = A.USER_ID join main.t_svc_ref SR on SR.SVC_ID = OS.SVC_ID where SR.Name like '%АУДИОТЕЛЕ%' --and OS.User_Id = 1013731 and OS.OTH_SVC_ID >= OW_HELPER.FN_GET_MIN_AU_UNPAYED_OTH_SVC(A.USER_ID, 0) order by A.USER_ID
-
> O'ShinW © (06.03.13 13:46) [1] > даже проще. > Уберем T_PLUS > Есть только T_MINUS и число. > Надо взять первые строки по дате, сумма которых по деньгам > не превышает заданное число.
Времени было мало, накидал примерно
-- Генерим тестовые значений DECLARE @S int
SET @S=100;
WITH MM(DT,S) AS ( select DT,S FROM ( SELECT CONVERT(datetime,'01/01/2000',103) AS DT,100 AS S union SELECT CONVERT(datetime,'02/01/2000',103) AS DT,100 AS S union SELECT CONVERT(datetime,'03/01/2000',103) AS DT,100 AS S union SELECT CONVERT(datetime,'04/01/2000',103) AS DT,100 AS S union SELECT CONVERT(datetime,'05/01/2000',103) AS DT,100 AS S )M )
-- Тестируем запрос по тестовым значениям SELECT DT,S FROM MM WHERE DT<= ( select MAX(DT) FROM MM M1 WHERE (select SUM(S) FROM MM M2 WHERE DATEDIFF(dd,M2.DT,M1.DT) >=0) <=@S )
-
> Вариант (06.03.13 15:51) [3]
и когда я так думать научусь.. :) Спасибо!
-
>O'ShinW © (06.03.13 16:15) [4] аналитические ф-ция sum в этой версии MS SQL есть?
-
> Кщд (07.03.13 10:46) [5]
есть :)
зы Я ткнул при выборе вопроса MSSQL, Oracle Мне надо и в той и в той БД написать Но показывает только MSSQL почему то.
-
>O'ShinW © (07.03.13 11:22) [6]тогда:
with q as (select to_date('01.01.2000', 'dd.mm.yyyy') dt, 100 val from dual
union all
select to_date('02.01.2000', 'dd.mm.yyyy'), 100 from dual
union all
select to_date('03.01.2000', 'dd.mm.yyyy'), 100 from dual
union all
select to_date('04.01.2000', 'dd.mm.yyyy'), 100 from dual
union all
select to_date('05.01.2000', 'dd.mm.yyyy'), 100 from dual
)
select w.dt, w.val
from
(
select q.dt, q.val, sum(q.val) over (order by q.dt) sm
from q q
) w
where w.sm < :predefined_number
-
>O'ShinW © (06.03.13 16:15) [4] ну, и - понятно - так думать(три(!) прохода по таблице), как в "Вариант (06.03.13 15:51) [3]", не надо) и тем более - делать
-
> Кщд (07.03.13 12:00) [7]
Ok. Примерно, понятно. Спасибо.
:) Завтра посмотрю Всех твоих дам - с праздником :)
-
>O'ShinW © (07.03.13 14:10) [9] аналогично)
-
Да, интересно и просто.
> over (order by
Учту. Спасибо.
Жаль, что не получится :) таблица T_PLUS (доход) несколько сложнее, конечно, на самом деле. Там есть id поставщика услуги. Не ключ. то ли ошибка проектировки, то ли заплатка - но туда могут падать записи без указания id :(, с комментарием аля "а эти деньги надо перегнать поставщику такому-то" И на следующий день операторы разносят руками. Или через день,( два, 3, n если праздники) И все. Весь смысл теряется. Блин.
|