2017-08-11 11 views
-1

:私は必要なもの使用前の行の値MS SQLの「XMLパスの」内

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ため すなわち、(7万=10万 - 3万)/(60,000 =7万 - 10,000)/(45,000 = 60,000 - 15,000)

以下

は私のクエリです:

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 

あなたが見ることができるように、 TOTAL_LOAN_AMOUNTが一定で、次の行に計算(A.TOTAL_LOAN_AMOUNT - CAST(B.SCHEDULE_AMOUNT AS MONEY))が蓄積されていないため、SCHEDULE_PRINCIPALが正しくありませんでした。

予想されるレポートのように結果を出力できる計算方法はありますか?私はSQL Server 2012を使用しています。どんな助力も高く評価されます。

答えて

0

試してみてください、この(私はSCHEDULE_DATE BY(B.SCHEDULE_AMOUNT)OVER(ORDER)SUMとSCHEDULE_AMOUNTを置き換える:

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でMONEYにする必要があります。次に、私はあなたのクエリを使用して、システムは、次のエラーを返しました: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

2つの他の回答の詳細としては、中心的な考えがある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)。 –

関連する問題