Поворотная таблица в SQL - PullRequest
0 голосов
/ 17 июня 2019

У меня проблема с подходом, как развернуть эту таблицу:

Как я могу преобразовать это:

Не могли бы вы дать мне подсказки (не полный код), как это сделать? я действительно не знаю, с чего мне начать (я не знаю, является ли это типичным разворотом, разворачивающимся)

+------+------+--------+----------+-----------+-----+
| ColI | Col2 | Month  | Turnover | Provision | Fee |
+------+------+--------+----------+-----------+-----+
|  123 | Asdf | 201810 |    10000 |      100  | 0,1 |
|  123 | Asdf | 201811 |    20000 |       200 | 0,2 |
|  123 | Asdf | 201812 |    30000 |       300 | 0,3 |
+------+------+--------+----------+-----------+-----+

в это:

+------+------+---------------+-----------------+------------+---------------+-----------------+------------+---------------+-----------------+-----------+
| ColI | Col2 | Turnover20810 | Provision201810 | Fee201810  | Turnover20811 | Provision201811 | Fee201811  | Turnover20812 | Provision201812 | Fee201812 |
+------+------+---------------+-----------------+------------+---------------+-----------------+------------+---------------+-----------------+-----------+
|  123 | Asdf |         10000 |            100  |        0,1 |         20000 |             200 |        0,2 |         30000 |             300 |       0,3 |
+------+------+---------------+-----------------+------------+---------------+-----------------+------------+---------------+-----------------+-----------+

Спасибо!

Ответы [ 3 ]

3 голосов
/ 17 июня 2019

Если предположить, что каждая группа ColI, Col2 будет иметь максимум три записи, тогда мы можем попытаться повернуть, используя ROW_NUMBER:

WITH cte AS (
    SELECT *,
        ROW_NUMBER() OVER (PARTITION BY ColI, Col2 ORDER BY Month) rn
    FROM yourTable
)

SELECT
    ColI,
    Col2,
    MAX(CASE WHEN rn = 1 THEN Turnover END) AS Turnover1,
    MAX(CASE WHEN rn = 1 THEN Provision END) AS Provision1,
    MAX(CASE WHEN rn = 1 THEN Fee END) AS Fee1,
    MAX(CASE WHEN rn = 2 THEN Turnover END) AS Turnover2,
    MAX(CASE WHEN rn = 2 THEN Provision END) AS Provision2,
    MAX(CASE WHEN rn = 2 THEN Fee END) AS Fee2,
    MAX(CASE WHEN rn = 3 THEN Turnover END) AS Turnover3,
    MAX(CASE WHEN rn = 3 THEN Provision END) AS Provision3,
    MAX(CASE WHEN rn = 3 THEN Fee END) AS Fee3
FROM cte
GROUP BY
    ColI,
    Col2;

Обратите внимание, что я не вводил более конкретные имена столбцов, чтобы сделать запрос как можно более общим. Например, возможно, может быть другая ColI, Col2 группа, у которой будут другие три месяца.

2 голосов
/ 17 июня 2019

Используя Dynamic Sql

IF OBJECT_ID('tempdb..#TEMP') IS NOT NULL
DROP TABLE #TEMP
;WITH CTE (ColI , Col2 , Month  , Turnover , Provision , Fee )
AS
(
SELECT 123 , 'Asdf' , 201810 ,    10000 ,100  ,'0,1' UNION ALL 
SELECT 123 , 'Asdf' , 201811 ,    20000 ,200 , '0,2' UNION ALL 
SELECT 123 , 'Asdf' , 201812 ,    30000 ,300 , '0,3' 
)
SELECT ColI , Col2,Turnover , Provision , Fee,MixedCol,Reqcol , ROW_NUMBER()OVER(ORDER BY (SELECT NULL)) AS Seq
INTO #Temp 
FROM CTE 
CROSS APPLY (VALUES (CONCAT('Turnover','_',[Month]),CAST(Turnover AS VARCHAR(20))),
                    (CONCAT('Provision','_',[Month]),CAST(Provision AS VARCHAR(20))),
                    (CONCAT('Fee','_',[Month]),CAST(Fee AS VARCHAR(20)))
            )DT  (MixedCol,Reqcol)

DECLARE  @Sql nvarchar(max),
         @DynamicColumn nvarchar(max),
         @MaxDynamicColumn nvarchar(max)

SELECT @DynamicColumn = STUFF((SELECT  ', '+QUOTENAME(CAST(MixedCol AS VARCHAR(100)))
FROM #TEMP ORDER BY Seq  FOR XML PATH ('')),1,1,'') 

SELECT @MaxDynamicColumn = STUFF((SELECT  ', '+'MAX('+QUOTENAME(CAST(MixedCol AS VARCHAR(100)))+') AS '+QUOTENAME(CAST(MixedCol AS VARCHAR(100)))
FROM #TEMP ORDER BY Seq  FOR XML PATH ('')),1,1,'') 

SET @Sql=' SELECT  ColI , Col2,'+ @MaxDynamicColumn+'
            FROM
            (
            SELECT * FROM #TEMP
            )AS src
            PIVOT 
            (
            MAX(Reqcol) FOR [MixedCol] IN ('+@DynamicColumn+')
            ) AS Pvt
            GROUP BY ColI , Col2 '
EXEC (@Sql)
PRINT @Sql
0 голосов
/ 17 июня 2019

Q: «... дайте мне подсказки (не весь код), как это сделать»

A: Этот пример с динамической транспонированием таблицы. Вы можете попробовать это. Отключите исходный стол и транспонируйте.

CREATE table #tbl (
    color varchar(10), Paul int, John int, Tim int, Eric int);
insert #tbl select 
    'Red' ,1 ,5 ,1 ,3 union all select
    'Green' ,8 ,4 ,3 ,5 union all select
    'Blue' ,2 ,2 ,9 ,1;

select * FROM #tbl

--1) Transpose. Example without dynamic code. You create list of fields in query
select *
from #tbl
unpivot (value for name in ([Paul],[John],[Tim],[Eric])) up
pivot (max(value) for color in ([Blue],[Green],[Red])) p


--2) Transpose. Example with dynamic code, without names of fields.
DECLARE @cols NVARCHAR(MAX), @query NVARCHAR(MAX), @rows NVARCHAR(MAX)='';
-- XML with all values
SET @cols = STUFF(
                 (
                     SELECT DISTINCT
                            ','+QUOTENAME(T.Color)  -- Name of first column
                     FROM #tbl T FOR XML PATH(''), TYPE
                 ).value('.', 'nvarchar(max)'), 1, 1, '');

SELECT @rows=@rows+','+QUOTENAME(Name) 
FROM 
(SELECT Name,ROW_NUMBER() OVER(ORDER BY column_id) AS 'RowNum' 
FROM tempdb.sys.Columns 
WHERE Object_ID = OBJECT_ID('tempdb..#tbl') 
) AS A WHERE A.RowNum>1
SET @rows=STUFF(@rows,1,1,'')

SET @query='SELECT *
from #tbl
unpivot (value for name in ('+@rows+')) up
pivot (max(value) for color in ('+@Cols+')) p'

EXEC (@query)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...