Конференция "Базы" » Не соображу с запросом [MSSQL]
 
  • O'ShinW © (06.03.13 12:59) [0]
    две таблицы
    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х дней,
    апятый день остался не погашен.
  • O'ShinW © (06.03.13 13:46) [1]
    даже проще.
    Уберем T_PLUS
    Есть только T_MINUS и число.
    Надо взять первые строки по дате, сумма которых по деньгам не превышает заданное число.

    через функцию написал уже
    , где (курсором) вычитается из параметра, пока разность >=0
    но на приличных объемах это работает долго
  • O'ShinW © (06.03.13 14:59) [2]
    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
  • Вариант (06.03.13 15:51) [3]

    > 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
    )
  • O'ShinW © (06.03.13 16:15) [4]

    > Вариант   (06.03.13 15:51) [3]

    и когда я так думать научусь.. :)
    Спасибо!
  • Кщд (07.03.13 10:46) [5]
    >O'ShinW ©   (06.03.13 16:15) [4]
    аналитические ф-ция sum в этой версии MS SQL есть?
  • O'ShinW © (07.03.13 11:22) [6]

    > Кщд   (07.03.13 10:46) [5]

    есть :)

    зы
    Я ткнул при выборе вопроса MSSQL, Oracle
    Мне надо и в той и в той БД написать
    Но показывает только MSSQL почему то.
  • Кщд (07.03.13 12:00) [7]
    >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


  • Кщд (07.03.13 12:41) [8]
    >O'ShinW ©   (06.03.13 16:15) [4]
    ну, и - понятно - так думать(три(!) прохода по таблице), как в "Вариант   (06.03.13 15:51) [3]", не надо)
    и тем более - делать
  • O'ShinW © (07.03.13 14:10) [9]

    > Кщд   (07.03.13 12:00) [7]

    Ok. Примерно, понятно.
    Спасибо.

    :)
    Завтра посмотрю
    Всех твоих дам - с праздником :)
  • Кщд (07.03.13 21:47) [10]
    >O'ShinW ©   (07.03.13 14:10) [9]
    аналогично)
  • O'ShinW © (11.03.13 09:08) [11]
    Да, интересно и просто.

    > over (order by

    Учту. Спасибо.

    Жаль, что не получится :)
    таблица T_PLUS (доход) несколько сложнее, конечно, на самом деле.
    Там есть id поставщика услуги. Не ключ.
    то ли ошибка проектировки, то ли заплатка - но туда могут падать записи без указания id :(, с комментарием аля "а эти деньги надо перегнать поставщику такому-то"
    И на следующий день операторы разносят руками. Или через день,( два, 3,  n если праздники)
    И все. Весь смысл теряется. Блин.
 
Конференция "Базы" » Не соображу с запросом [MSSQL]
Есть новые Нет новых   [119448   +45][b:0][p:0.002]