Запрос с несколькими столбцами PIVOT, разными именами и агрегированными - PullRequest
0 голосов
/ 24 апреля 2019

У меня есть следующая таблица CTE с именем assets (учтите, что количество учетных записей и номеров ISIN исчисляется десятками и сотнями):

+---------------------------+---------+----------------+---------------------+--------------------+----------+----------------------+------------------+--------+
|           Date            | Account |      ISIN      |      Quantity       |       Value        | Currency | Price                | PriceCHF         | FXRate |
+---------------------------+---------+----------------+---------------------+--------------------+----------+----------------------+------------------+--------+
| 2019-02-28 00:00:00       |       1 | CH5055181629   | 0.00000000          | 0.000000           | CHF      | 1124.56              | 1124.56          | 1      |
| 2019-02-28 00:00:00       |       6 | CH5055181629   | 0.37866100          | 425.827014         | CHF      | 1124.56              | 1124.56          | 1      |
| 2019-02-28 00:00:00       |       7 | CH5055181629   | 0.67151800          | 755.162282         | CHF      | 1124.56              | 1124.56          | 1      |
| 2019-02-28 00:00:00       |       8 | CH5055181629   | 0.45240000          | 508.750944         | CHF      | 1124.56              | 749.7067         | 1.5    |
| 2019-02-28 00:00:00       |       9 | CH5055181622   | 0.02204500          | 24.790925          | CHF      | 1124.56              | 749.7067         | 1.5    |
| 2019-02-28 00:00:00       |      10 | CH5055181622   | 0.08353300          | 93.937870          | CHF      | 1124.56              | 749.7067         | 1.5    |
| 2019-02-28 00:00:00       |      11 | CH5055181622   | 0.89667100          | 1008.360340        | CHF      | 1124.56              | 749.7067         | 1.5    |
+---------------------------+---------+----------------+---------------------+--------------------+----------+----------------------+------------------+--------+

Я хочу динамически изменять столбцы на основена ISIN.В настоящее время у меня есть следующий запрос:

SELECT * 
INTO   #assets 
FROM   (SELECT xxx 
        FROM   yyyy) a 

DECLARE @cols  AS NVARCHAR(max), 
        @query AS NVARCHAR(max); 

SET @cols = Stuff((SELECT DISTINCT ',' + Quotename(c.ISIN) 
                   FROM   #assets c 
                   FOR xml path(''), type).value('.', 'NVARCHAR(MAX)'), 1, 1, '' 
            ) 
SET @query = 'SELECT date, account, ' + @cols 
             + ' from #assets x pivot ( max(quantity) for ISIN in (' + @cols 
             + ')) p ' 

EXECUTE(@query) 

DROP TABLE #assets

Результатом является таблица с датой, счетом и каждый столбец для ISIN имеет значение количества.Каждая связанная строка количества из исходного запроса имеет свое значение количества в поле, а остальные столбцы ISIN имеют значение NULL.

Теперь я хочу, чтобы столбцы были больше, чем количество.Я хочу, чтобы имя столбца было, например, ISIN + '_quantity' и ISIN + '_value'.Кроме того, я хочу, чтобы количественные значения были не индивидуальными для каждой строки, а агрегированными на Date и Account.

Итак, мой текущий результат следующий:

+---------------------------+---------+--------------+----------------+
|           Date            | Account | CH5055181629 | CH5055181622   |
+---------------------------+---------+--------------+----------------+
| 2019-02-28 00:00:00       |       1 | 0.000000     | NULL           |
| 2019-02-28 00:00:00       |       6 | 0.378661     | NULL           |
| 2019-02-28 00:00:00       |       7 | 0.671518     | NULL           |
| 2019-02-28 00:00:00       |       8 | 0.452400     | NULL           |
| 2019-02-28 00:00:00       |       9 | 0.000000     | NULL           |
| 2019-02-28 00:00:00       |      10 | 0.000000     | NULL           |
| 2019-02-28 00:00:00       |      11 | 0.000000     | NULL           |
| 2019-02-28 00:00:00       |       1 | NULL         | 0.000000       |
| 2019-02-28 00:00:00       |       6 | NULL         | 0.000000       |
| 2019-02-28 00:00:00       |       7 | NULL         | 0.000000       |
| 2019-02-28 00:00:00       |       8 | NULL         | 0.000000       |
| 2019-02-28 00:00:00       |       9 | NULL         | 0.022045       |
| 2019-02-28 00:00:00       |      10 | NULL         | 0.083533       |
| 2019-02-28 00:00:00       |      11 | NULL         | 0.896671       |
+---------------------------+---------+--------------+----------------+

Мой желаемый результат теперь будет следующим:

+---------------------------+---------+-----------------------+-----------------------+--------------------+--------------------+
|           Date            | Account | CH5055181629_quantity | CH5055181622_quantity | CH5055181629_value | CH5055181622_value |
+---------------------------+---------+-----------------------+-----------------------+--------------------+--------------------+
| 2019-02-28 00:00:00       |       1 | 0.000000              | 0.000000              | 0.000000           | 0.000000           |
| 2019-02-28 00:00:00       |       6 | 0.378661              | 0.000000              | 425.827014         | 0.000000           |
| 2019-02-28 00:00:00       |       7 | 0.671518              | 0.000000              | 755.162282         | 0.000000           |
| 2019-02-28 00:00:00       |       8 | 0.452400              | 0.000000              | 508.750944         | 0.000000           |
| 2019-02-28 00:00:00       |       9 | 0.000000              | 0.022045              | 0.000000           | 24.790925          |
| 2019-02-28 00:00:00       |      10 | 0.000000              | 0.083533              | 0.000000           | 93.937870          |
| 2019-02-28 00:00:00       |      11 | 0.000000              | 0.896671              | 0.000000           | 1'008.360340       |
+---------------------------+---------+-----------------------+-----------------------+--------------------+--------------------+

Я застрял в точке, где я хочу иметь два базовых столбца и агрегацию.

1 Ответ

1 голос
/ 24 апреля 2019

Возможно, это не самое красивое решение, но ... Я использую два центра (один для количества и один для значения) для глобальных временных таблиц и затем присоединяю их:

Таблица:

Create Table #tbl
(
  Dt Date,
  Account Int,
  ISIN VarChar(20),
  Quantity Float,
  Val Float,
  Currency VarChar(3),
  Price Float,
  PriceCHF Float,
  FXRate Float
)
Insert Into #tbl Values
('2019-02-28 00:00:00', 1,'CH5055181629',0.00000000,0.000000,'CHF',1124.56,1124.56,1),
('2019-02-28 00:00:00', 6,'CH5055181629',0.37866100,425.827014,'CHF',1124.56,1124.56,1),
('2019-02-28 00:00:00', 7,'CH5055181629',0.67151800,755.162282,'CHF',1124.56,1124.56,1),
('2019-02-28 00:00:00', 8,'CH5055181629',0.45240000,508.750944,'CHF',1124.56,749.7067,1.5),
('2019-02-28 00:00:00', 9,'CH5055181622',0.02204500,24.790925,'CHF',1124.56,749.7067,1.5),
('2019-02-28 00:00:00',10,'CH5055181622',0.08353300,93.937870,'CHF',1124.56,749.7067,1.5),
('2019-02-28 00:00:00',11,'CH5055181622',0.89667100,1008.360340,'CHF',1124.56,749.7067,1.5)

Pivot 1:

SELECT * 
INTO   #assets 
FROM   (SELECT * 
        FROM   #tbl) a 

DECLARE @cols1  AS NVARCHAR(max)
DECLARE @cols1q  AS NVARCHAR(max) 
Declare @query AS NVARCHAR(max); 

SET @cols1 = Stuff((SELECT DISTINCT ',' + Quotename(c.ISIN) 
                   FROM   #assets c 
                   FOR xml path(''), type).value('.', 'NVARCHAR(MAX)'), 1, 1, '' 
            ) 

SET @cols1q = Stuff((SELECT DISTINCT ',' + 'Cast(ISNULL(##pvt1.' + c.ISIN + ',0) As Decimal(15,6)) As ' + c.ISIN + '_Quantity'
                   FROM   #assets c 
                   FOR xml path(''), type).value('.', 'NVARCHAR(MAX)'), 1, 1, '' 
)
SET @query = 'SELECT dt, account, ' + @cols1 
             + ' Into ##pvt1 from #assets x pivot ( max(quantity) for ISIN in (' + @cols1 
             + ')) p ' 

EXECUTE(@query) 

Pivot 2:

SELECT * 
INTO   #assets2 
FROM   (SELECT * 
        FROM   #tbl) a 

DECLARE @cols2  AS NVARCHAR(max) 
DECLARE @cols2v  AS NVARCHAR(max) 
--        ,@query AS NVARCHAR(max); 

SET @cols2 = Stuff((SELECT DISTINCT ',' + Quotename(c.ISIN) 
                   FROM   #assets2 c 
                   FOR xml path(''), type).value('.', 'NVARCHAR(MAX)'), 1, 1, '' 
            ) 

SET @cols2v = Stuff((SELECT DISTINCT ',' + 'Cast(ISNULL(##pvt2.' + c.ISIN + ',0) As Decimal(15,6)) As ' + c.ISIN + '_Value' 
                   FROM   #assets2 c 
                   FOR xml path(''), type).value('.', 'NVARCHAR(MAX)'), 1, 1, '' 
            ) 


SET @query = 'SELECT dt, account, ' + @cols2 
             + ' Into ##pvt2 from #assets x pivot ( sum(val) for ISIN in (' + @cols2 
             + ')) p ' 

EXECUTE(@query) 

Присоединение к центрам:

Set @query = 

'Select 
       ##pvt1.Dt,
       ##pvt1.Account,' + @cols1q + ', ' + @cols2v +

' From ##pvt1 Inner Join
              ##pvt2 On ##pvt1.Account = ##pvt2.Account
Order By ##pvt1.Account'

EXECUTE(@query) 

Очистка:

Drop Table #assets
Drop Table #assets2
Drop Table ##pvt1
Drop Table ##pvt2
Drop Table #tbl
...