Как создать динамический SQL для имен столбцов, которые являются датами на конец квартала?

#sql #sql-server #tsql #pivot

#sql #sql-сервер #tsql #поворотный

Вопрос:

У меня есть три таблицы, которые выглядят следующим образом.

 --TABLE1
--DROP TABLE POR
CREATE TABLE POR
( IDRSSD varchar(10),
  Institution  VARCHAR(100),
  Filing_Type int)
INSERT INTO POR
  (IDRSSD, Institution, Filing_Type)
VALUES
  ('53540', 'Wells', 3)
INSERT INTO POR
  (IDRSSD, Institution, Filing_Type)
VALUES
  ('53550', 'BofA', 1)
INSERT INTO POR
  (IDRSSD, Institution, Filing_Type)
VALUES
  ('53560', 'Chase', 2)
INSERT INTO POR
  (IDRSSD, Institution, Filing_Type)
VALUES
  ('53570', 'JPM', 4)

--TABLE2
--DROP TABLE RCA
CREATE TABLE RCA
( IDRSSD varchar(10),
  Schedule_Code  VARCHAR(10),
  Line_Item varchar(100),
  Code varchar(10),
  [2019Q4] varchar(10),
  [2019Q3] varchar(10),
  [2019Q2] varchar(10),
  [2019Q1] varchar(10),
  [2018Q4] varchar(10),
  [2018Q3] varchar(10))

INSERT INTO RCA
  (IDRSSD, Schedule_Code, Line_Item, Code, [2019Q4], [2019Q3], [2019Q2], [2019Q1], [2018Q4], [2018Q3])
VALUES
  ('53540', 'RC', 'Cash amp; Noninterest-bearing Deps', 'RCFD1881',  '127000', '146000', '9370', '1000', '1300', '12000')

INSERT INTO RCA
  (IDRSSD, Schedule_Code, Line_Item, Code, [2019Q4], [2019Q3], [2019Q2], [2019Q1], [2018Q4], [2018Q3])
VALUES
  ('53540', 'RC', 'Cash amp; Noninterest-bearing Deps', 'RCFD1881',  '4390', '8220', '7570', '9800', '11230', '15570')

INSERT INTO RCA
  (IDRSSD, Schedule_Code, Line_Item, Code, [2019Q4], [2019Q3], [2019Q2], [2019Q1], [2018Q4], [2018Q3])
VALUES
  ('53560', 'RC', 'Cash amp; Noninterest-bearing Deps', 'RCFD1881',  '14390', '8220', '700', '4800', '1230', '57')

INSERT INTO RCA
  (IDRSSD, Schedule_Code, Line_Item, Code, [2019Q4], [2019Q3], [2019Q2], [2019Q1], [2018Q4], [2018Q3])
VALUES
  ('53560', 'RC', 'Cash amp; Noninterest-bearing Deps', 'RCFD1881',  '9000', '2200', '5700', '980', '300', '5570')

--TABLE3
--DROP TABLE Mapping
CREATE TABLE Mapping
( Schedule_Code varchar(10),
  Call_Report  VARCHAR(100))

INSERT INTO Mapping
(Schedule_Code, Call_Report)
VALUES
('RC', 'Balance Sheet')
INSERT INTO Mapping
(Schedule_Code, Call_Report)
VALUES
('RCA', 'Cash and Balances')
INSERT INTO Mapping
(Schedule_Code, Call_Report)
VALUES
('RCB', 'Securities')
 

Теперь я могу легко объединять таблицы следующим образом (детская игра для вас, экспертов).

 Select RCA.[IDRSSD],
       POR.Institution,
       POR.Filing_Type,
       RCA.Schedule_Code,
       Map.Call_Report,
       RCA.Line_Item,
       RCA.Code,
       Right(RCA.Code,4) As Harmonized_Code,
       RCA.[2019Q4],
       RCA.[2019Q3],
       RCA.[2019Q2],
       RCA.[2019Q1],
       RCA.[2018Q4],
       RCA.[2018Q3]
From [RCA] As RCA
INNER JOIN [POR] As POR
ON RCA.IDRSSD = POR.IDRSSD
INNER JOIN Mapping As Map
ON RCA.Schedule_Code = Map.Schedule_Code
 

Результат:

[![введите описание изображения здесь][1]][1]

Что я хочу сделать, это попытаться динамически изменять даты окончания квартала, потому что кварталы будут время от времени меняться (иногда у нас будет больше кварталов, а иногда у нас будет меньше). Итак, я бы хотел, чтобы конечный результат выглядел так, если это возможно.

[![][2]][2]

Возможно ли это, или это слишком сложно?

Я попробовал это, и заработал небольшой свод, но он не присоединяется к двум другим таблицам и не суммирует сумму. Кроме того, очевидно, что мои имена столбцов вообще не являются динамическими.

 SELECT [IDRSSD], Qtr, Amt
FROM   
   (SELECT [IDRSSD], [2019Q4], [2019Q3], [2019Q2], [2019Q1], [2018Q4], [2018Q3] 
   FROM RCA
   ) p  
UNPIVOT  
   (Amt FOR Qtr IN   
      ([2019Q4], [2019Q3], [2019Q2], [2019Q1], [2018Q4], [2018Q3])  
)AS unpvt 
 

[![введите описание изображения здесь][3]][3]

Я тоже попробовал это, и это не дало большого прогресса.

 DECLARE @colsUnpivot AS NVARCHAR(MAX),
   @query  AS NVARCHAR(MAX)

select @colsUnpivot 
  = stuff((select ',' quotename(C.name)
           FROM sys.columns c
           WHERE c.object_id = OBJECT_ID('dbo.[RCA]') 
           for xml path('')), 1, 1, '')
--print(@colsUnpivot)

set @query 
  = 'select *
     from [RCA]
     unpivot
     (
        data
        for d in ('''  @colsunpivot  ''')
     ) u'
print(@query)
 

Результат:

 select *
     from [RCA]
     unpivot
     (
        data
        for d in ('[IDRSSD],[Schedule_Code],[Code],[2019Q4],[2019Q3],[2019Q2],[2019Q1],[2018Q4],[2018Q3]')
     ) u
 

Комментарии:

1. Задумывались ли вы о том, чтобы переделать дизайн, чтобы сохранить его в таблице без привязки (т.Е. Нормализованным)?

Ответ №1:

Вы можете получить данные, используя ПЕРЕКРЕСТНОЕ ПРИМЕНЕНИЕ и применение агрегата, как указано ниже:

 Select RCA.[IDRSSD],
       POR.Institution,
       POR.Filing_Type,
       RCA.Schedule_Code,
       Map.Call_Report,
       RCA.Line_Item,
       RCA.Code,
       Right(RCA.Code,4) As Harmonized_Code,
       Q.QuarterEnd, sum(cast(Q.Amount as int)) as Amount
From [RCA] As RCA
INNER JOIN [POR] As POR
ON RCA.IDRSSD = POR.IDRSSD
INNER JOIN Mapping As Map
ON RCA.Schedule_Code = Map.Schedule_Code
CROSS APPLY
(
VALUES
('2019Q4', RCA.[2019Q4]),
('2019Q3', RCA.[2019Q3]),
       ('2019Q2',RCA.[2019Q2]),
       ('2019Q1', RCA.[2019Q1]),
       ('2018Q4',RCA.[2018Q4]),
       ('2018Q3', RCA.[2018Q3])
) AS Q(QuarterEnd,Amount) 
GROUP BY RCA.[IDRSSD],POR.Institution, POR.Filing_Type,RCA.Schedule_Code,Call_Report, Line_Item,Code,QuarterEnd 
 

Комментарии:

1. Я думаю, что это почти работает! Я только что обновил свой исходный пост своими выводами.

2. Это работает, я допустил ошибку с моей стороны. Ваш код работает.

3. Большое вам спасибо!! Еще один быстрый вопрос: могу ли я сделать даты динамическими с помощью этого перекрестного применения? Что-то вроде: FROMDATE, TODATE… ГДЕ Quarter_End МЕЖДУ приведением (floor(приведение (из даты с плавающей запятой)) как datetime) И приведением (floor(приведение (к дате с плавающей запятой)) как datetime)

4. @ASH, да. у вас может быть динамический способ выполнения, используя ПЕРЕКРЕСТНОЕ ПРИМЕНЕНИЕ. У вас может быть предложение WHERE в предложении ПЕРЕКРЕСТНОГО ПРИМЕНЕНИЯ. Вы можете передать значение из внешнего запроса и добавить в предложение WHERE в предложении ПЕРЕКРЕСТНОГО ПРИМЕНЕНИЯ.

5. Как я могу это сделать? Я попробовал это: ЗНАЧЕНИЯ (‘2019Q4’, RCA.[2019Q4]), (‘2019Q3’,RCA.[2019Q3]), (‘2019Q2’,RCA.[2019Q2]), (‘2019Q1’, RCA.[2019Q1]), (‘2018Q4’,RCA.[2018Q4]), (‘2018Q3’, RCA.[2018Q3]) (‘2018Q2′,RCA.[2018Q2]) ) КАК Q(конец квартала, сумма) Где Q.QuarterEnd>=’2016Q1’ Но когда даты отсутствуют в заголовках таблицы, я получаю сообщение об ошибке. Я надеялся сделать его несколько динамичным, поэтому, если дата есть, возьмите ее, а если нет, пропустите. Возможно ли это?