使用'中的上一行值;对于XML路径';在MS SQL中

使用'中的上一行值;对于XML路径';在MS SQL中,sql,sql-server,sql-server-2012,Sql,Sql Server,Sql Server 2012,我有以下表格: 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

我有以下表格:

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 
附表_本金按(未偿本金-附表_金额)计算。 i、 e.对于客户XXX,(70000=100000-30000)/(60000=70000-10000)/(45000=60000-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
正如您所看到的,明细表本金是错误的,因为总贷款金额是恒定的,并且计算(A.TOTAL\u LOAN\u AMOUNT-CAST(B.SCHEDULE\u AMOUNT As MONEY))未累积到下一行

有什么方法可以像预期的报告那样输出结果呢?我正在使用SQL Server 2012。任何帮助都将不胜感激。

尝试以下方法(我用SUM(B.计划金额)替换计划金额)(按计划日期订购):


正如另外两个答案所详细说明的,中心思想是
SUM()。(在原始问题中,
CUSTOMER\u LOAN
SCHEDULE
已作为表格存在,可以从CTE中删除。)


这应该是您想要的。关键位是前面的无边界行,这是运行总数

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

抱歉,我已更新查询。B.SCHEDULE_金额应转换为货币。然后我使用您的查询,系统返回以下错误:范围窗口框架的按列表排序不能包含LOB类型的表达式。我更新了查询,但您不应将日期存储在varchar(max)列中。请勿使用
转换(varchar,…)
。这相当于这里的
CONVERT(VARCHAR(30),…)
,但这一点并不明显。(具体地说,它的长度“无论如何都不能满足输入参数的长度”。)使用不带长度的
VARCHAR
是一个错误。
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
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)
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