SQL - возврат даты и суммы последнего платежа - PullRequest
0 голосов
/ 04 мая 2018

Я создал следующий запрос в Oracle, чтобы вернуть самую последнюю дату платежа и соответствующую сумму платежа от клиента. Это работает, потому что я не включил поле Сумма. Если я это сделаю, это приведет к нескольким строкам на компанию. Большое спасибо заранее.

РАБОТАЕТ (но не включает последнюю сумму)

SELECT COMPANY_NAME, TERM_CODE, 
MAX(LAST_PYMT) AS LAST_PYMT_REC, 
AR_BALANCE, MAX_CREDIT_AR, OFFSET_BALANCE AS CREDITBAL_W_AP_OFFSETS 
FROM 
(
SELECT COMPANY_NAME,  s2.LAST_PYMT, s2.AMOUNT, 
CURRENT_BALANCE AS AR_BALANCE,
(CURRENT_BALANCE - AP_TOTAL) AS OFFSET_BALANCE,
TERM_CODES.TERM_CODE,
AP_TOTAL,
MAX_CREDIT AS MAX_CREDIT_AR
FROM COMPANIES s1
LEFT OUTER JOIN CTIRELAND.term_codes ON term_codes.tmc_auto_key = s1.tmc_auto_key

inner join
(
  select CR_DETAIL.ENTRY_DATE LAST_PYMT, MAX(CR_DETAIL.CRD_AUTO_KEY),
    CR_DETAIL.AMOUNT, CR_DETAIL.CMP_AUTO_KEY
  from CR_DETAIL
  GROUP BY CR_DETAIL.CRD_AUTO_KEY, CR_DETAIL.CMP_AUTO_KEY, CR_DETAIL.ENTRY_DATE, CR_DETAIL.AMOUNT
) s2
  on s1.CMP_AUTO_KEY = s2.CMP_AUTO_KEY 

  ORDER BY s1.company_name
  )
  GROUP BY COMPANY_NAME, AR_BALANCE, MAX_CREDIT_AR, OFFSET_BALANCE, TERM_CODE
  ORDER BY AR_BALANCE DESC

НЕ РАБОТАЕТ (возвращает каждую Сумму, произведенную каждой компанией, а не просто самую последнюю)

SELECT COMPANY_NAME, TERM_CODE, 
MAX(LAST_PYMT) AS LAST_PYMT_REC, <strong>AMOUNT</strong>, 
AR_BALANCE, MAX_CREDIT_AR, OFFSET_BALANCE AS CREDITBAL_W_AP_OFFSETS 
FROM 
(
SELECT COMPANY_NAME,  s2.LAST_PYMT, s2.AMOUNT, 
CURRENT_BALANCE AS AR_BALANCE,
(CURRENT_BALANCE - AP_TOTAL) AS OFFSET_BALANCE,
TERM_CODES.TERM_CODE,
AP_TOTAL,
MAX_CREDIT AS MAX_CREDIT_AR
FROM COMPANIES s1
LEFT OUTER JOIN CTIRELAND.term_codes ON term_codes.tmc_auto_key = s1.tmc_auto_key</p>

<p>inner join
(
  select CR_DETAIL.ENTRY_DATE LAST_PYMT, MAX(CR_DETAIL.CRD_AUTO_KEY),
    CR_DETAIL.AMOUNT, CR_DETAIL.CMP_AUTO_KEY
  from CR_DETAIL
  GROUP BY CR_DETAIL.CRD_AUTO_KEY, CR_DETAIL.CMP_AUTO_KEY, CR_DETAIL.ENTRY_DATE, CR_DETAIL.AMOUNT
) s2
  on s1.CMP_AUTO_KEY = s2.CMP_AUTO_KEY </p>

<p>ORDER BY s1.company_name
  )
  GROUP BY COMPANY_NAME, AR_BALANCE, MAX_CREDIT_AR, OFFSET_BALANCE, TERM_CODE, <strong>AMOUNT</strong>
  ORDER BY AR_BALANCE DESC

Ответы [ 2 ]

0 голосов
/ 05 мая 2018

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

Тестовые таблицы

-- helper table
create table T
as
select 
  level as companyid
from dual
connect by level <= 4 ;

-- table used for queries
create table T2
as
select 
  A.companyid
, trunc( dbms_random.value * 1000 ) as amount
, to_date( trunc( dbms_random.value( 2446081, 2458243 ) ), 'J' ) paymentdate
from T A, T B ;

Данные

SQL> select * from T2 order by companyid, paymentdate desc ;

COMPANYID  AMOUNT  PAYMENTDATE  
1          766     27-MAY-95 -- <- required 
1          198     12-APR-90    
1          554     05-AUG-89    
1          82      27-FEB-87    
2          195     07-AUG-07 -- <- required      
2          623     07-OCT-03    
2          903     01-NOV-93    
2          519     09-NOV-88    
3          561     27-JUN-97 -- <- required      
3          335     05-SEP-92    
3          327     25-JAN-87    
3          967     04-AUG-85    
4          623     10-APR-17 -- <- required      
4          912     24-FEB-12    
4          385     08-APR-01    
4          708     10-MAR-87 

16 rows selected. 

Проблема в том, что мы хотим, чтобы последняя ОПЛАТА, включая СУММУ, для каждой КОМПАНИИ - что-то вроде следующего запроса, который НЕ работает ...

select 
  companyid
, max( paymentdate )
, amount               -- cannot get the amount of the last payment(date)
from T2
group by companyid ;
-- ORA-00979: not a GROUP BY expression

Если мы теперь добавим больше столбцов в предложение GROUP BY, мы получим слишком много групп (как это было бы). Это произошло с вами, когда вы только что добавили столбец AMOUNT в предложения SELECT и GROUP BY.

-- if we code
-- ... group by companyid, paymentdate, amount
-- then we get all rows (again) -> no use
select 
  companyid
, max( paymentdate )
, amount              
from T2
group by companyid, paymentdate, amount ;

-- 16 rows selected. (output omitted)

Использование аналитических функций позволяет нам «группировать» строки другим способом, записывая (разбиение по ...). Обратите внимание, что предложение GROUP BY отсутствует в этом запросе. Мы получаем необходимые ДАТЫ ОПЛАТЫ и т. Д.

select distinct
  companyid
, max( paymentdate ) over ( partition by companyid ) mostrecentpayment
, first_value( amount ) over ( partition by companyid order by paymentdate desc ) amount
from T2 
order by companyid ;

-- result
COMPANYID  MOSTRECENTPAYMENT  AMOUNT  
1          27-MAY-95          766     
2          07-AUG-07          195     
3          27-JUN-97          561     
4          10-APR-17          623 

Используя подход @ Vivek, для той же тестовой таблицы (набор результатов такой же, как указано выше):

select 
  companyid
, paymentdate
, amount
from (
  select 
    companyid
  , paymentdate
  , rank() over ( partition by companyid order by paymentdate desc ) rank_
  , amount               
  from T2 
) where rank_ = 1 ;

COMPANYID  PAYMENTDATE  AMOUNT  
1          27-MAY-95    766     
2          07-AUG-07    195     
3          27-JUN-97    561     
4          10-APR-17    623 

Протестировано с Oracle 12c. Примечание: значения в T2 являются случайными!

0 голосов
/ 04 мая 2018

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

select COMPANY_NAME, TERM_CODE, LAST_PYMT LAST_PYMT_REC, AR_BALANCE, MAX_CREDIT_AR,CREDITBAL_W_AP_OFFSETS
(SELECT  COMPANY_NAME, TERM_CODE, LAST_PYMT LAST_PYMT_REC, AR_BALANCE, MAX_CREDIT_AR, OFFSET_BALANCE AS CREDITBAL_W_AP_OFFSETS,
        rank() over (partition by COMPANY_NAME, AR_BALANCE, MAX_CREDIT_AR, OFFSET_BALANCE, TERM_CODE order by last_pymt desc) rn 
FROM 
    (SELECT COMPANY_NAME,  s2.LAST_PYMT, s2.AMOUNT, CURRENT_BALANCE AS AR_BALANCE, (CURRENT_BALANCE - AP_TOTAL) AS OFFSET_BALANCE,
            TERM_CODES.TERM_CODE,AP_TOTAL,MAX_CREDIT AS MAX_CREDIT_AR
    FROM COMPANIES s1
    LEFT OUTER JOIN CTIRELAND.term_codes ON term_codes.tmc_auto_key = s1.tmc_auto_key
    inner join
    (
      select CR_DETAIL.ENTRY_DATE LAST_PYMT, MAX(CR_DETAIL.CRD_AUTO_KEY),
        CR_DETAIL.AMOUNT, CR_DETAIL.CMP_AUTO_KEY
      from CR_DETAIL
      GROUP BY CR_DETAIL.CRD_AUTO_KEY, CR_DETAIL.CMP_AUTO_KEY, CR_DETAIL.ENTRY_DATE, CR_DETAIL.AMOUNT
    ) s2
      on s1.CMP_AUTO_KEY = s2.CMP_AUTO_KEY 
      ORDER BY s1.company_name)
) m
where m.rn = 1
ORDER BY AR_BALANCE DESC;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...