Как свернуть несколько строк в одну в сводной таблице - PullRequest
1 голос
/ 03 октября 2019

Я относительно неопытен в коде SQL, поэтому здесь.

Я хотел бы извлечь данные из таблицы и использовать PIVOT для преобразования значений в заголовки столбцов.

Мне удалось достичьчто я хочу, используя команду PIVOT (и динамические имена полей), но я надеялся, что все значения для одного ref появятся в одной строке. Тем не менее, я получаю одну строку для каждого кода со значением в исходной таблице (см. Результаты ниже).

Использование CROSS APPLY, кажется, является подходящим способом (это закомментировано в моем примере кода), но у меня естьстолкнулся с несколькими проблемами:

  1. Я не могу понять, как это работает, поэтому адаптация онлайн-примеров к моему сценарию потребовала некоторых догадок.
  2. Я вошел (что я думаю)правильные ссылки в команде в соответствии с другим постом на этом сайте: Повернуть таблицу по значению, но сгруппировать данные по одной строке по другой? , где они утверждали, что оба значения в VALUES должны быть одинаковымитип данных для отмены процесса. Однако установка значения 'varchar (10) останавливает работу функции SUM внутри оператора PIVOT. Запуск его в виде десятичного числа / числа с плавающей запятой приводит к получению всех результатов NULL.
  3. При заданном десятичном значении 'value', включая инструкцию GROUP BY, получается одна строка данных, однако (как в пункте 2) все значения кода равны NULL.

Надеюсь, все это имеет смысл. Пожалуйста, посоветуйте, как я могу свернуть результаты ниже в одну строку. Заранее спасибо.

DECLARE @CODES nvarchar(max)
select @CODES =
    stuff(
    (
    select distinct ',[' + code + ']'
    from codetable
    for xml path('')
    ),
    1,1,'')

DECLARE @SQL nvarchar(max)
SET @SQL = 
N'
SELECT
    ref,
    ' + @CODES + ',
FROM
    codetable
    --CROSS APPLY
    --(
 --   VALUES
 --     (''code'', convert(varchar(10), code, 120)),
 --     (''value'', convert(decimal, value))
    --) CA (CODE, VAL)
PIVOT(SUM(value)
    FOR code IN (' + @CODES + '))
    AS PVTTable2
WHERE
    ref = ''101'' AND end_date IS NULL
GROUP BY ref,' + @CODES + '
'
exec sp_executesql @SQL
My original table is like this:
-------------------------
|ref    |CODES  |VALUE  |
-------------------------
|101    |CODE4  |20     |
|101    |CODE1  |2      |
|101    |CODE7  |38     |


The results I get are:
-------------------------------------------------------------------------
|ref    |CODE1  |CODE2  |CODE3  |CODE4  |CODE5  |CODE6  |CODE7  |CODE8  |
-------------------------------------------------------------------------
|101    |NULL   |NULL   |NULL   |20     |NULL   |NULL   |NULL   |NULL   |
|101    |2      |NULL   |NULL   |NULL   |NULL   |NULL   |NULL   |NULL   |
|101    |NULL   |NULL   |NULL   |NULL   |NULL   |NULL   |38     |NULL   |

Ответы [ 2 ]

0 голосов
/ 03 октября 2019

Пивот должен быть записан как:

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

SET @cols = STUFF((SELECT distinct ',' + QUOTENAME(T.CODES) 
            FROM codetable T
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')


set @query = 'SELECT ref, ' + @cols + ' from 
            (
             SELECT
                 ref, --< grouping column >,
                 CODES, --< spreading column >, 
                 VALUE --< aggregation column >
             FROM codetable
           ) PivotData
            pivot 
            (
                sum(VALUE)
                for CODES in (' + @cols + ')
            ) p '

exec sp_executesql @query

пример кода здесь ..

0 голосов
/ 03 октября 2019

GROUP BY ref только

DECLARE @CODES nvarchar(max)
select @CODES =
    stuff(
    (
    select distinct ',[' + code + ']'
    from codetable
    for xml path('')
    ),
    1,1,'');

DECLARE @CODESGrp nvarchar(max)
select @CODESGrp =
    stuff(
    (
    select distinct ',min([' + code + '])'
    from codetable
    for xml path('')
    ),
    1,1,''); 

DECLARE @SQL nvarchar(max);
SET @SQL = 'SELECT  ref,' + @CODESGrp 
+ ' FROM  codetable '
+ ' PIVOT(SUM(value) FOR code IN (' + @CODES + ')) AS PVTTable2'
+ ' WHERE ref = 101 GROUP BY ref' ;

exec sp_executesql @SQL;
...