2017-08-11 18 views
-1

我有如下表:使用上一行值

TABLE A (CUSTOMER_LOAN): 
============================= 
CUSTOMER_ID TOTAL_LOAN_AMOUNT 
XXX   100,000.00 
YYY   200,000.00 

TABLE B (SCHEDULE): 
========================================= 
CUSTOMER_ID SCHEDULE_DATE SCHEDULE_AMOUNT 
XXX   20170102  30,000   
XXX   20170302  10,000   
XXX   20170602  15,000   
YYY   20170203  50,000   
YYY   20170403  100,000   
YYY   20170703  30,000   

我需要的是得到以下的輸出:

EXPECTED REPORT OUTPUT : 
============================= 
CUSTOMER_ID SCHEDULE_DATES     SCHEDULE_PRINCIPAL 
XXX   20170102/20170302/20170602  70,000/60,000/45,000 
YYY   20170203/20170403/20170703  150,000/50,000/20,000 

的SCHEDULE_PRINCIPAL是按(傑出校長 - SCHEDULE_AMOUNT)計算。 即客戶XXX,(70,000 = 100,000 - 30,000)/(60,000 = 70000 - 10,000)/(45,000 = 60,000 - 15000)

下面是我的查詢:

SELECT A.CUSTOMER_ID 
, STUFF((SELECT '/' + SCHEDULE_DATE FROM SCHEDULE B 
     WHERE B.CUSTOMER_ID = A.CUSTOMER_ID 
     FOR XML PATH('')), 1, 1, '') AS SCHEDULE_DATES 
, STUFF((SELECT '/' + (A.TOTAL_LOAN_AMOUNT - CAST(B.SCHEDULE_AMOUNT AS MONEY)) FROM SCHEDULE B 
     WHERE B.CUSTOMER_ID = A.CUSTOMER_ID 
     FOR XML PATH('')), 1, 1, '') AS SCHEDULE_PRINCIPAL 
FROM CUSTOMER_LOAN A 

正如你所看到的, SCHEDULE_PRINCIPAL錯誤,因爲TOTAL_LOAN_AMOUNT是常量,計算(A.TOTAL_LOAN_AMOUNT - CAST(B.SCHEDULE_AMOUNT AS MONEY))未在下一行累積。

任何方式來做這樣的計算,可以輸出結果,如預期的報告?我正在使用SQL Server 2012.任何幫助將不勝感激。

回答

0

試試這個(我替換SUM SCHEDULE_AMOUNT(B.SCHEDULE_AMOUNT)OVER(ORDER BY SCHEDULE_DATE):

SELECT A.CUSTOMER_ID 
, STUFF((SELECT '/' + SCHEDULE_DATE FROM SCHEDULE B 
     WHERE B.CUSTOMER_ID = A.CUSTOMER_ID 
     FOR XML PATH('')), 1, 1, '') AS SCHEDULE_DATES 
, STUFF((SELECT '/' + CAST(A.TOTAL_LOAN_AMOUNT - SUM(CAST(B.SCHEDULE_AMOUNT AS MONEY)) OVER(ORDER BY CAST(SCHEDULE_DATE AS VARCHAR(8))) AS VARCHAR(MAX)) 
     FROM SCHEDULE B 
     WHERE B.CUSTOMER_ID = A.CUSTOMER_ID 
     FOR XML PATH('')), 1, 1, '') AS SCHEDULE_PRINCIPAL 
FROM CUSTOMER_LOAN A 
+0

對不起,我更新了查詢。 B.SCHEDULE_AMOUNT應該作爲貨幣CAST。然後,我使用您的查詢,系統返回以下錯誤:RANGE窗口框架的ORDER BY列表不能包含LOB類型的表達式。 – TinySimonH

+0

我更新了我的查詢,但不應該在varchar(max)列中存儲日期 –

+0

謝謝!您的查詢解決了我的問題。 – TinySimonH

0
with 
Principals as 
(
select b.*,TOTAL_LOAN_AMOUNT-SUM(SCHEDULE_AMOUNT) over (partition by b.CUSTOMER_ID order by SCHEDULE_DATE) principal from CUSTOMER_LOAN a 
inner join SCHEDULE b 
on a.CUSTOMER_ID=b.CUSTOMER_ID 
) 
select 
    CUSTOMER_ID 
    ,(
    STUFF((SELECT '/' + SCHEDULE_DATE FROM SCHEDULE B 
     WHERE B.CUSTOMER_ID = A.CUSTOMER_ID 
     FOR XML PATH('')), 1, 1, '') 

    ) Schedule_Dates 
    ,STUFF((SELECT '/' + (convert(varchar(255),cast(b.principal as money),1)) FROM Principals B 
     WHERE B.CUSTOMER_ID = A.CUSTOMER_ID 
     FOR XML PATH('')), 1, 1, '') AS SCHEDULE_PRINCIPAL 
from CUSTOMER_LOAN a 
1

至於其他兩個答案細節,中心思想是SUM() OVER()獲得運行總計但是,讓我們也炫耀公用表表達式,構造函數,CONCATCROSS APPLY雖然我們在它。(在原來的問題,CUSTOMER_LOANSCHEDULE已經存在的表,可以留出CTE的。)

WITH CUSTOMER_LOAN AS ( 
    SELECT * FROM (VALUES 
     ('XXX', $100000), 
     ('YYY', $200000) 
    ) AS CUSTOMER_LOAN(CUSTOMER_ID, TOTAL_LOAN_AMOUNT) 
), SCHEDULE AS (
    SELECT * FROM (VALUES 
     ('XXX', '20170102', $30000), 
     ('XXX', '20170302', $10000), 
     ('XXX', '20170602', $15000), 
     ('YYY', '20170203', $50000), 
     ('YYY', '20170403', $100000), 
     ('YYY', '20170703', $30000) 
    ) AS SCHEDULE(CUSTOMER_ID, SCHEDULE_DATE, SCHEDULE_AMOUNT) 
), PRINCIPALS AS (
    SELECT 
     S.CUSTOMER_ID, 
     S.SCHEDULE_DATE, 
     L.TOTAL_LOAN_AMOUNT - SUM(S.SCHEDULE_AMOUNT) OVER (
      PARTITION BY S.CUSTOMER_ID 
      ORDER BY S.SCHEDULE_DATE 
     ) AS SCHEDULE_PRINCIPAL 
    FROM SCHEDULE S 
    JOIN CUSTOMER_LOAN L ON S.CUSTOMER_ID = L.CUSTOMER_ID 
) 
SELECT CUSTOMER_ID, T.* 
FROM CUSTOMER_LOAN CROSS APPLY (
    SELECT STUFF((
     SELECT CONCAT('/', P.SCHEDULE_DATE) 
     FROM PRINCIPALS P 
     WHERE P.CUSTOMER_ID = CUSTOMER_LOAN.CUSTOMER_ID 
     ORDER BY P.SCHEDULE_DATE 
     FOR XML PATH('') 
    ), 1, 1, ''), 
    STUFF((
     SELECT CONCAT('/', P.SCHEDULE_PRINCIPAL) 
     FROM PRINCIPALS P 
     WHERE P.CUSTOMER_ID = CUSTOMER_LOAN.CUSTOMER_ID 
     ORDER BY P.SCHEDULE_DATE 
     FOR XML PATH('') 
    ), 1, 1, '') 
) T(SCHEDULE_DATES, SCHEDULE_PRINCIPAL) 
0

這應該得到你想要的。關鍵是ROWS UNBOUNDED PRECEDING,這是運行總數。

CREATE TABLE #CUSTOMER_LOAN (CUSTOMER_ID INT, TOTAL_LOAN_AMOUNT 

DECIMAL(38,2)); 
CREATE TABLE #SCHEDULE (CUSTOMER_ID INT, SCHEDULE_DATE VARCHAR(8), SCHEDULE_AMOUNT DECIMAL(38,2)); 

INSERT INTO #CUSTOMER_LOAN (CUSTOMER_ID, TOTAL_LOAN_AMOUNT) VALUES (1, 100000.00); 
INSERT INTO #CUSTOMER_LOAN (CUSTOMER_ID, TOTAL_LOAN_AMOUNT) VALUES (2, 200000.00); 

INSERT INTO #SCHEDULE (CUSTOMER_ID, SCHEDULE_DATE, SCHEDULE_AMOUNT) VALUES (1,'20170102',30000.00); 
INSERT INTO #SCHEDULE (CUSTOMER_ID, SCHEDULE_DATE, SCHEDULE_AMOUNT) VALUES (1,'20170202',10000.00); 
INSERT INTO #SCHEDULE (CUSTOMER_ID, SCHEDULE_DATE, SCHEDULE_AMOUNT) VALUES (1,'20170602',15000.00); 
INSERT INTO #SCHEDULE (CUSTOMER_ID, SCHEDULE_DATE, SCHEDULE_AMOUNT) VALUES (2,'20170203',50000.00); 
INSERT INTO #SCHEDULE (CUSTOMER_ID, SCHEDULE_DATE, SCHEDULE_AMOUNT) VALUES (2,'20170403',100000.00); 
INSERT INTO #SCHEDULE (CUSTOMER_ID, SCHEDULE_DATE, SCHEDULE_AMOUNT) VALUES (2,'20170703',30000.00); 

; WITH CTE AS 
(
    SELECT A.CUSTOMER_ID, 
     B.SCHEDULE_DATE, 
     a.TOTAL_LOAN_AMOUNT 
      - SUM(B.SCHEDULE_AMOUNT) OVER (PARTITION BY A.CUSTOMER_ID 
              ORDER BY B.SCHEDULE_DATE 
              ROWS UNBOUNDED PRECEDING) AS SCHEDULE_PRINCIPAL 
    FROM #CUSTOMER_LOAN A 
    INNER JOIN #SCHEDULE B ON A.CUSTOMER_ID = B.CUSTOMER_ID 
) 
SELECT CUSTOMER_ID, 
    LEFT(MAX(SCHEDULE_DATES), LEN(MAX(SCHEDULE_DATES))-1), 
    LEFT(MAX(SCHEDULE_PRINCIPALS), LEN(MAX(SCHEDULE_PRINCIPALS))-1) 
FROM CTE 
CROSS APPLY 
(
    SELECT CTE2.SCHEDULE_DATE + '/' 
    FROM CTE CTE2 
    WHERE CTE.CUSTOMER_ID = CTE2.CUSTOMER_ID 
    ORDER BY CTE2.SCHEDULE_DATE 
    FOR XML PATH('') 
) D (SCHEDULE_DATES) 
CROSS APPLY 
(
    SELECT CONVERT(VARCHAR, CTE2.SCHEDULE_PRINCIPAL) + '/' 
    FROM CTE CTE2 
    WHERE CTE.CUSTOMER_ID = CTE2.CUSTOMER_ID 
    ORDER BY CTE.SCHEDULE_DATE 
    FOR XML PATH('') 
) P (SCHEDULE_PRINCIPALS) 
GROUP BY CTE.CUSTOMER_ID 
+0

請勿使用'CONVERT(VARCHAR,...)'。這相當於'CONVERT(VARCHAR(30),...)',但這不過是顯而易見的。 (具體來說,它沒有達到「對於輸入參數足夠長的長度,不管是什麼」)。使用'VARCHAR'沒有長度是[踢壞習慣](http://sqlblog.com/blogs /aaron_bertrand/archive/2009/10/09/bad-habits-to-kick-declaring-varchar-without-length.aspx)。 –