选择多个记录上的最大日期类型

时间:2013-02-18 22:43:34

标签: sql oracle

CREATE TABLE PAYMENTS
(
   CTRL_NO       NUMBER                          NOT NULL,
   CUSTOMER_NO   NUMBER                          NOT NULL,
   CTYPE         VARCHAR2(10 BYTE)               NOT NULL,
   AMOUNT        NUMBER,
   PAYMENT_DATE  DATE
  )

CREATE UNIQUE INDEX TEST1_PK ON PAYMENTS
(CTRL_NO)

ALTER TABLE PAYMENTS ADD (
  CONSTRAINT TEST1_PK
 PRIMARY KEY
 (CTRL_NO)
    USING INDEX 

Insert into PAYMENTS
   (CTRL_NO, CUSTOMER_NO, CTYPE, AMOUNT, PAYMENT_DATE)
 Values
   (266, 272, 'CASH', -47, TO_DATE('12/09/2011 00:00:00', 'MM/DD/YYYY HH24:MI:SS'));
Insert into PAYMENTS
   (CTRL_NO, CUSTOMER_NO, CTYPE, AMOUNT, PAYMENT_DATE)
 Values
   (286, 272, 'CASH', 47, TO_DATE('12/12/2011 00:00:00', 'MM/DD/YYYY HH24:MI:SS'));
Insert into PAYMENTS
   (CTRL_NO, CUSTOMER_NO, CTYPE, AMOUNT, PAYMENT_DATE)
 Values
   (701, 272, 'CASH', -200, TO_DATE('12/13/2011 00:00:00', 'MM/DD/YYYY HH24:MI:SS'));
Insert into PAYMENTS
   (CTRL_NO, CUSTOMER_NO, CTYPE, AMOUNT, PAYMENT_DATE)
 Values
   (752, 272, 'INV', -91, TO_DATE('01/11/2012 00:00:00', 'MM/DD/YYYY HH24:MI:SS'));
Insert into .PAYMENTS
   (CTRL_NO, CUSTOMER_NO, CTYPE, AMOUNT, PAYMENT_DATE)
 Values
   (307, 252, 'AUTO', -9.35, TO_DATE('12/12/2011 00:00:00', 'MM/DD/YYYY HH24:MI:SS'));
Insert into .PAYMENTS
   (CTRL_NO, CUSTOMER_NO, CTYPE, AMOUNT, PAYMENT_DATE)
 Values
   (126, 252, 'AUTO', -128, TO_DATE('12/05/2011 00:00:00', 'MM/DD/YYYY HH24:MI:SS'));
Insert into .PAYMENTS
   (CTRL_NO, CUSTOMER_NO, CTYPE, AMOUNT, PAYMENT_DATE)
 Values
   (86, 252, 'INV', -18, TO_DATE('12/05/2011 00:00:00', 'MM/DD/YYYY HH24:MI:SS'));
Insert into .PAYMENTS
   (CTRL_NO, CUSTOMER_NO, CTYPE, AMOUNT, PAYMENT_DATE)
 Values
   (5890, 400, 'CASH', 120, TO_DATE('03/07/2012 00:00:00', 'MM/DD/YYYY HH24:MI:SS'));
Insert into .PAYMENTS
   (CTRL_NO, CUSTOMER_NO, CTYPE, AMOUNT, PAYMENT_DATE)
 Values
   (5888, 400, 'CASH', 76.41, TO_DATE('03/07/2012 00:00:00', 'MM/DD/YYYY HH24:MI:SS'));
Insert into .PAYMENTS
   (CTRL_NO, CUSTOMER_NO, CTYPE, AMOUNT, PAYMENT_DATE)
 Values
   (5886, 400, 'CASH', 86.34, TO_DATE('03/07/2012 00:00:00', 'MM/DD/YYYY HH24:MI:SS'));
Insert into .PAYMENTS
   (CTRL_NO, CUSTOMER_NO, CTYPE, AMOUNT, PAYMENT_DATE)
 Values
   (5680, 400, 'CASH', 158.97, TO_DATE('03/06/2012 00:00:00', 'MM/DD/YYYY HH24:MI:SS'));
Insert into .PAYMENTS
   (CTRL_NO, CUSTOMER_NO, CTYPE, AMOUNT, PAYMENT_DATE)
 Values
   (5819, 400, 'CASH', -40.94, TO_DATE('03/06/2012 00:00:00', 'MM/DD/YYYY HH24:MI:SS'));
Insert into .PAYMENTS
   (CTRL_NO, CUSTOMER_NO, CTYPE, AMOUNT, PAYMENT_DATE)
 Values
   (718, 400, 'INV', -40.04, TO_DATE('12/21/2011 00:00:00', 'MM/DD/YYYY HH24:MI:SS'));
COMMIT;

我想获得最后一笔现金交易的金额(金额)。如果没有,那么只需返回0。

这是我到目前为止的查询:

select p1.customer_no, max( p1.payment_date ) , 
( select nvl(sum(p2.amount), 0) 
  from payments p2
  where p2.ctype = 'CASH' 
  and p2.customer_no = p1.customer_no
   ) as last_payment_date 
 from payments p1
 group by p1.customer_no
  order by p1.customer_no ;

问题是272应该是11-jan-12 -200,但上面的查询返回13-dec-11 -200。另外,我应该得到400 7-mar-12 282.75而不是400.78。

3 个答案:

答案 0 :(得分:1)

试试这个

WITH CTE AS
(
select p1.customer_no, max(p1.payment_date) max_dt  
from payments p1
group by p1.customer_no
), CTE2 AS
(
select A.customer_no, sum(A.amount) amount 
from payments A 
WHERE ctype = 'CASH' 
AND payment_date = (SELECT max(x.payment_date) 
                    FROM payments X WHERE X.ctype = 'CASH'
                    AND A.customer_no = X.customer_no)
group by A.customer_no
)
SELECT A.customer_no, A.max_dt, nvl(amount,0) amount 
FROM CTE A
LEFT OUTER JOIN CTE2 B 
ON A.customer_no = B.customer_no 
ORDER BY A.customer_no;

SQL DEMO

答案 1 :(得分:0)

select p1.customer_no, max( p1.payment_date ) , 0
from payments p1
where not exists ( select 1 from payments p2 where p2.customer_no = p1.customer_no and ctype = 'CASH' ) 
group by p1.customer_no

 union

select p1.customer_no, payment_date, nvl(sum(amount),0)
from payments p1 inner   join ( select customer_no, max(payment_date ) as max_date from payments where ctype = 'CASH'  group by customer_no ) subQ
on  ( p1.customer_no = subQ.customer_no
       and p1.payment_date = subQ.max_date 
) 
group by p1.payment_date, p1.customer_no
感觉很痛苦。

答案 2 :(得分:0)

不确定您的预期输出,但这是我的版本 - 您将看到针对ctype = CASH的每一行的最后付款日期。您可以使用主查询中的WHERE限制输出。您可以使用LAG()填充空白等... 270 CASH最大日期是12/13/2011,而不是这个日期1/11/2012 bcs ctype = INV在JAN。你有疑问。插入值时出错了。希望它有所帮助:

SELECT customer_no
 , ctype
 , amount
 , payment_date
 , ( SELECT max(payment_date) 
       FROM stack_test
      WHERE ctype = 'CASH' 
        AND a.customer_no = customer_no
        AND a.ctype = ctype
   ) last_payment_date
 FROM stack_test a
 /

CUSTOMER_NO    CTYPE    AMOUNT    PAYMENT_DATE    LAST_PAYMENT_DATE
-------------------------------------------------------------------
272            CASH       -47       12/9/2011     12/13/2011
272            CASH        47       12/12/2011    12/13/2011
272            CASH      -200       12/13/2011    12/13/2011 -- This is CASH max date --
272            INV       -91        1/11/2012                -- This is INV max date not CASH --
252            AUTO      -9.35      12/12/2011    
252            AUTO      -128       12/5/2011    
252            INV       -18        12/5/2011    
400            CASH      120        3/7/2012       3/7/2012
400            CASH      76.41      3/7/2012       3/7/2012
400            CASH      86.34      3/7/2012       3/7/2012
400            CASH      158.97     3/6/2012       3/7/2012
400            CASH      -40.94     3/6/2012       3/7/2012
400             INV      -40.04     12/21/2011    

根据您的意见提供更多示例:

-- Max date by trans type --
  SELECT ctype, max(payment_date) max_cash_date
   FROM stack_test
  GROUP BY ctype
 ORDER BY 2
 /

CTYPE    MAX_CASH_DATE
-----------------------
AUTO    12/12/2011
INV     1/11/2012
CASH    3/7/2012

-- Example of using analytic functions - not needed in this case --
SELECT * FROM
(
SELECT customer_no, ctype
    , MAX(payment_date) OVER (PARTITION BY ctype ORDER BY ctype) max_cash_date
    , ROW_NUMBER() OVER (PARTITION BY ctype ORDER BY ctype) rno
    , amount
 FROM stack_test
 )
-- WHERE rno=1  -- Optional - retunrns same rows as above --
ORDER BY ctype
/