我在Oracle中创建了以下查询,以便从客户返回最近的付款日期和相应的付款金额。它的工作原理是因为我没有包含Amount字段。如果我这样做,每个公司会产生多行。 非常感谢提前。
工作(但不包括最近的金额)
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, AMOUNT, 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_keyinner 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, AMOUNT ORDER BY AR_BALANCE DESC
答案 0 :(得分:0)
尝试以下代码,希望它能解决您的要求。我添加了一个排名,根据最后一个付款日期查找排名,然后我在排名上过滤您的数据,这样您就可以得到所有其他列的排名=" 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;
答案 1 :(得分:0)
当编写一个与问题中的查询一样复杂的查询时,很容易出错(或两个)。由于我们手头没有任何真实的休息数据,我宁愿给你一个简化的例子,当你将所提出的原则应用到你自己的查询中时,应该允许你自己找到正确的解决方案。正如@Vivek所建议的那样,使用分析函数(参见documentation和examples)将是获得所需结果集的一种方法。
测试表
-- 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.
问题是:我们想要为每个公司提供最新的PAYMENTDATE,包括其AMOUNT - 类似于以下查询,这不起作用......
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)
使用分析函数允许我们通过编写(partition by ...)以不同的方式“分组”行。请注意,此查询中缺少GROUP BY子句。我们得到了所需的PAYMENTDATE等。
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中的值是随机的!