Поработав с временной версией вашего стола, я, наконец, понял это. Однако сначала следует отметить несколько вещей.
- Поскольку вы пытаетесь повернуть два столбца, вы должны повернуть их по отдельности, а затем соединить подрезультаты вместе.
- Так как мы собираемся использовать
@cols
для обеих сводок, нам нужно создать версию переменной @cols
, которая будет псевдонимом динамически создаваемых имен столбцов сводки для окончательного выбора.
Итак, давайте углубимся в код.
Сначала мы создадим строки, которые будут содержать наши динамически создаваемые имена столбцов.
DECLARE @colsAll AS NVARCHAR(MAX);
DECLARE @cols AS NVARCHAR(MAX);
SET @cols =
STUFF((
SELECT DISTINCT
',' + QUOTENAME(CONVERT(VARCHAR(30), DENSE_RANK() OVER ( PARTITION BY a.account ORDER BY a.ratechangedate)))
FROM MARS_DW.dbo.vw_GTMScheduledRateAndPaymentChangesWithAccountNumber_Archive a
INNER JOIN
(
SELECT account
FROM mars..vw_loans
WHERE loanstatus <> 'bk payment plan'
) b ON a.account = b.account
WHERE
a.ArchiveDate = '5/21/2019'
AND a.AppliedDate > '1/2/2018'
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)'), 1, 1, ''
)
SET @colsAll =
STUFF((
SELECT DISTINCT
',' + 'd.' + QUOTENAME(CONVERT(VARCHAR(30), DENSE_RANK() OVER ( PARTITION BY account ORDER BY ratechangedate ))) + ' AS [Date'
+ CONVERT(VARCHAR(30), DENSE_RANK() OVER ( PARTITION BY account ORDER BY ratechangedate )) + '], ' + 'r.'
+ QUOTENAME(CONVERT(VARCHAR(30), DENSE_RANK() OVER ( PARTITION BY account ORDER BY ratechangedate ))) + ' AS [Rate'
+ CONVERT(VARCHAR(30), DENSE_RANK() OVER ( PARTITION BY account ORDER BY ratechangedate )) + ']'
FROM MARS_DW.dbo.vw_GTMScheduledRateAndPaymentChangesWithAccountNumber_Archive a
INNER JOIN
(
SELECT account
FROM mars..vw_loans
WHERE loanstatus <> 'bk payment plan'
) b ON a.account = b.account
WHERE
a.ArchiveDate = '5/21/2019'
AND a.AppliedDate > '1/2/2018'
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)'), 1, 1, ''
)
При настройке @colsAll
я использую псевдонимы таблиц, которые будут определены при окончательном выборе.
А теперь для генерации пивота:
DECLARE @query AS NVARCHAR(MAX);
SET @query = ';WITH dates as (SELECT Account, ' + @cols
+ ' from
(
select a.Account
, a.ratechangedate
, DateIndex = CONVERT(VARCHAR(30), DENSE_RANK() OVER ( PARTITION BY a.account ORDER BY a.ratechangedate ))
from MARS_DW.dbo.vw_GTMScheduledRateAndPaymentChangesWithAccountNumber_Archive a
INNER JOIN (SELECT account
FROM mars..vw_loans
WHERE loanstatus <> ''bk payment plan''
) b ON a.account = b.account
WHERE a.ArchiveDate = ''5/21/2019'' AND a.AppliedDate > ''1/2/2018''
) x
pivot
(
min(ratechangedate)
for DateIndex in (' + @cols + ')
) d)
,rates as (SELECT Account, ' + @cols
+ ' from
(
select a.Account
, a.new_noterate
, RateIndex = CONVERT(VARCHAR(30), DENSE_RANK() OVER ( PARTITION BY a.account ORDER BY a.ratechangedate ))
from #vw_GTMScheduledRateAndPaymentChangesWithAccountNumber_Archive a
INNER JOIN (SELECT account
FROM mars..vw_loans
WHERE loanstatus <> ''bk payment plan''
) b ON a.account = b.account
WHERE a.ArchiveDate = ''5/21/2019'' AND a.AppliedDate > ''1/2/2018''
) x
pivot
(
min(new_noterate)
for RateIndex in (' + @cols + ')
) r)
SELECT d.Account, ' + @colsAll + '
FROM dates d
JOIN rates r ON d.Account = r.Account'
EXECUTE ( @query )
Если бы вы PRINT
запросили, вы бы увидели запрос, который будет запущен. Мне всегда нравится PRINT
запрос, а затем скопировать и вставить результат в новое окно запроса и запустить его. Если появляются какие-либо ошибки, проще отладить окончательный запрос, чем пытаться отлаживать динамический sql. Для справки, запрос, который выплевывается с помощью приведенного выше кода выглядит следующим образом:
;WITH dates AS
(
SELECT
Account
,[1]
,[2]
,[3]
FROM
(
SELECT
a.Account
,a.ratechangedate
,DateIndex = CONVERT(VARCHAR(30), DENSE_RANK() OVER ( PARTITION BY a.account
ORDER BY a.ratechangedate
)
)
FROM MARS_DW.dbo.vw_GTMScheduledRateAndPaymentChangesWithAccountNumber_Archive a
INNER JOIN
(
SELECT account
FROM mars..vw_loans
WHERE loanstatus <> 'bk payment plan'
) b ON a.account = b.account
WHERE
a.ArchiveDate = '5/21/2019'
AND a.AppliedDate > '1/2/2018'
) x
PIVOT
(
MIN(ratechangedate)
FOR DateIndex IN ( [1]
,[2]
,[3]
)
) d
)
,rates AS
(
SELECT
Account
,[1]
,[2]
,[3]
FROM
(
SELECT
a.Account
,a.new_noterate
,RateIndex = CONVERT(VARCHAR(30), DENSE_RANK() OVER ( PARTITION BY a.account
ORDER BY a.ratechangedate
)
)
FROM #vw_GTMScheduledRateAndPaymentChangesWithAccountNumber_Archive a
INNER JOIN
(
SELECT account
FROM mars..vw_loans
WHERE loanstatus <> 'bk payment plan'
) b ON a.account = b.account
WHERE
a.ArchiveDate = '5/21/2019'
AND a.AppliedDate > '1/2/2018'
) x
PIVOT
(
MIN(new_noterate)
FOR RateIndex IN ( [1]
,[2]
,[3]
)
) r
)
SELECT
d.Account
,d.[1] AS Date1
,r.[1] AS Rate1
,d.[2] AS Date2
,r.[2] AS Rate2
,d.[3] AS Date3
,r.[3] AS Rate3
FROM dates d
JOIN rates r ON d.Account = r.Account
EDIT:
Вот обновленная версия запроса, которая дополняет имена столбцов сводки начальными нулями, чтобы создать трехзначный порядковый номер.
SET @cols =
STUFF((
SELECT DISTINCT
',' + QUOTENAME(RIGHT(('00'+CONVERT(VARCHAR(30), DENSE_RANK() OVER ( PARTITION BY a.account ORDER BY a.ratechangedate ))),3))
FROM MARS_DW.dbo.vw_GTMScheduledRateAndPaymentChangesWithAccountNumber_Archive a
INNER JOIN
(
SELECT account
FROM mars..vw_loans
WHERE loanstatus <> 'bk payment plan'
) b ON a.account = b.account
WHERE
a.ArchiveDate = '5/21/2019'
AND a.AppliedDate > '1/2/2018'
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)'), 1, 1, ''
)
SET @colsAll =
STUFF((
SELECT DISTINCT
',' + 'd.' + QUOTENAME(RIGHT(('00'+CONVERT(VARCHAR(30), DENSE_RANK() OVER ( PARTITION BY a.account ORDER BY a.ratechangedate ))),3)) + ' AS [Date'
+ RIGHT(('00'+CONVERT(VARCHAR(30), DENSE_RANK() OVER ( PARTITION BY a.account ORDER BY a.ratechangedate ))),3) + '], ' + 'r.'
+ QUOTENAME(RIGHT(('00'+CONVERT(VARCHAR(30), DENSE_RANK() OVER ( PARTITION BY a.account ORDER BY a.ratechangedate ))),3)) + ' AS [Rate'
+ RIGHT(('00'+CONVERT(VARCHAR(30), DENSE_RANK() OVER ( PARTITION BY a.account ORDER BY a.ratechangedate ))),3) + ']'
FROM MARS_DW.dbo.vw_GTMScheduledRateAndPaymentChangesWithAccountNumber_Archive a
INNER JOIN
(
SELECT account
FROM mars..vw_loans
WHERE loanstatus <> 'bk payment plan'
) b ON a.account = b.account
WHERE
a.ArchiveDate = '5/21/2019'
AND a.AppliedDate > '1/2/2018'
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)'), 1, 1, ''
)
SET @query = ';WITH dates as (SELECT Account, ' + @cols
+ ' from
(
select a.Account
, a.ratechangedate
, DateIndex = RIGHT((''00''+CONVERT(VARCHAR(30), DENSE_RANK() OVER ( PARTITION BY a.account ORDER BY a.ratechangedate ))),3)
from MARS_DW.dbo.vw_GTMScheduledRateAndPaymentChangesWithAccountNumber_Archive a
INNER JOIN (SELECT account
FROM mars..vw_loans
WHERE loanstatus <> ''bk payment plan''
) b ON a.account = b.account
WHERE a.ArchiveDate = ''5/21/2019'' AND a.AppliedDate > ''1/2/2018''
) x
pivot
(
min(ratechangedate)
for DateIndex in (' + @cols + ')
) d)
,rates as (SELECT Account, ' + @cols
+ ' from
(
select a.Account
, a.new_noterate
, RateIndex = RIGHT((''00''+CONVERT(VARCHAR(30), DENSE_RANK() OVER ( PARTITION BY a.account ORDER BY a.ratechangedate ))),3)
from MARS_DW.dbo.vw_GTMScheduledRateAndPaymentChangesWithAccountNumber_Archive a
INNER JOIN (SELECT account
FROM mars..vw_loans
WHERE loanstatus <> ''bk payment plan''
) b ON a.account = b.account
WHERE a.ArchiveDate = ''5/21/2019'' AND a.AppliedDate > ''1/2/2018''
) x
pivot
(
min(new_noterate)
for RateIndex in (' + @cols + ')
) r)
SELECT d.Account, ' + @colsAll + '
FROM dates d
JOIN rates r ON d.Account = r.Account'