поворот строк в столбцы в tsql

У меня есть следующая таблица со следующими примерами данных

ID  Language       Question       SubQuestion     SubSubQuestion    TotalCount  TotalPercent
3      E               9               0                1             88527            73%
3      E               9               0                2             19684            16%
3      E               9               0                3             12960            11%
3      E               9               0                9              933              1%

Я хочу, чтобы все в один ряд, как это

    ID  Language        TotalCount901   TotalPercent901     TotalCount902   TotalPercent902 TotalCount903   TotalPercent903
     3       E            88527           73%                 19684             16%              12960              11%

Я устал использовать команду Pivot, но у меня она не работает.


person masfenix    schedule 01.11.2012    source источник
comment
Под не работает вы подразумеваете, что он выдает ошибку, дает нежелательные результаты, что-то еще?   -  person LittleBobbyTables - Au Revoir    schedule 02.11.2012
comment
Тестовая скрипта: sqlfiddle.com/#!3/3a3fc/1   -  person mellamokb    schedule 02.11.2012
comment
Каков критерий группировки? Является ли количество подпунктов/подподпунктов динамическим? Сложно выполнить поворот с динамическим количеством столбцов, так как вам потребуется использовать динамически генерируемый код SQL. Используете ли вы какой-либо язык приложения для отображения результатов, в которых вы могли бы выполнять поворот? Обычно это проще для сценариев с динамической шириной столбца.   -  person mellamokb    schedule 02.11.2012
comment
Это работает, но я не получаю желаемых результатов. Моя логика ошибочна. Могу отправить код, если нужно. @mellamokb, я считаю, что группировка должна быть по идентификатору и языку. То есть мне нужна только одна строка для идентификатора и языка (в моей реальной таблице у меня много идентификаторов и много языков).   -  person masfenix    schedule 02.11.2012
comment
Нет, sub/subsub/subsubsub не является динамическим. Их всегда будет трое. Если вы имеете в виду ценности, то тоже НЕТ! однако в них есть числовые значения   -  person masfenix    schedule 02.11.2012
comment
@masfenix: Хорошо, так будет намного проще :). Так вы всегда опускаете SubSubQuestion = 9?   -  person mellamokb    schedule 02.11.2012
comment
Что значит оставить? Может быть, я могу перефразировать это. Для каждой комбинации Q, SubQ, SubSUBQ мне нужна одна строка. Имеет ли это смысл?   -  person masfenix    schedule 02.11.2012
comment
@masfenix: я имею в виду, что в вашем примере у вас есть подподвопросы 1, 2, 3 и 9. Но в вашем выводе у вас есть только Total*901, Total*902 и Total*903. А как насчет Total*909?   -  person mellamokb    schedule 02.11.2012


Ответы (1)


Я сделал несколько предположений на основе ваших имен столбцов, но похоже, что вы хотите использовать что-то похожее на это. Это относится как к UNPIVOT, так и к PIVOT, чтобы получить значения в запрошенных вами столбцах:

select *
from
(
  select id,
    language,
    col + cast(QUESTION as varchar(10))
      +cast(subquestion as varchar(10))
      +cast(SubSubQuestion as varchar(10)) col,
    value
  from
  (
    select id, language,
      cast(TotalCount as varchar(10)) TotalCount, 
      totalPercent,
      question, subquestion, SubSubQuestion
    from yourtable
  ) usrc
  unpivot
  (
    value 
    for col in (totalcount, totalpercent)
  ) un
) srcpiv
pivot
(
  max(value)
  for col in ([TotalCount901], [totalPercent901], 
              [TotalCount902], [totalPercent902], 
              [TotalCount903], [totalPercent903],
              [TotalCount909], [totalPercent909])
) p

См. SQL Fiddle с демонстрацией.

Примечание: при выполнении UNPIVOT столбцы должны быть одного типа данных. Если это не так, вам нужно будет преобразовать/преобразовать, чтобы получить одинаковые типы данных.

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

DECLARE @query  AS NVARCHAR(MAX),
    @colsPivot as  NVARCHAR(MAX)


select @colsPivot 
  = STUFF((SELECT  ',' 
             + QUOTENAME(c.name +
                        cast(QUESTION as varchar(10))
                        +cast(subquestion as varchar(10))
                        +cast(SubSubQuestion as varchar(10)))
           from yourtable t
           cross apply sys.columns as C
           where C.object_id = object_id('yourtable') and
              C.name in ('TotalCount', 'TotalPercent')
           group by c.name, t.question, t.subquestion, t.subsubquestion
           order by t.SubSubQuestion
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')


set @query = 'select *
              from
              (
                select id,
                  language,
                  col + cast(QUESTION as varchar(10))
                    +cast(subquestion as varchar(10))
                    +cast(SubSubQuestion as varchar(10)) col,
                  value
                from
                (
                  select id, language,
                    cast(TotalCount as varchar(10)) TotalCount, 
                    totalPercent,
                    question, subquestion, SubSubQuestion
                  from yourtable
                ) usrc
                unpivot
                (
                  value 
                  for col in (totalcount, totalpercent)
                ) un
              ) srcpiv
            pivot 
            (
                max(value)
                for col in (' + @colsPivot + ')
            ) p '

execute(@query)

См. SQL Fiddle с демонстрацией.

person Taryn    schedule 01.11.2012
comment
+1 Отличный ответ. Я бы только предположил, что OP пропускает запись SubSubQuestion = 9. Кроме того, вот доказательство того, что он также обрабатывает сценарии с несколькими идентификаторами и языками: sqlfiddle.com/#! 3/b91b0/1 - person mellamokb; 02.11.2012
comment
@mellamokb я тоже так думал, но предположил, что это часть имени столбца. Не уверен, хотя, поскольку требования не на 100% ясны. И я включил все значения только для примера. - person Taryn; 02.11.2012
comment
Я использовал ваш, но везде были нули. Я снова посмотрю на запрос, чтобы увидеть, не пропустил ли я что-нибудь - person masfenix; 02.11.2012
comment
@masfenix, если вы включите дополнительные поля в PIVOT часть запроса, вы можете получить нули, вам нужно включить только те поля, которые необходимы для выполнения преобразования - person Taryn; 02.11.2012
comment
Я не добавлял и не удалял поля, просто изменил несколько имен (поскольку имена полей моей таблицы немного отличаются (хотел быть в безопасности и не публиковать данные компании)). Я обновлю и дам вам знать. Огромное спасибо. Похоже, sqlfiddle - это именно то, что мне нужно. РЕДАКТИРОВАТЬ: нашел ошибку. Спасибо, парни. и вау красивый ответ. - person masfenix; 02.11.2012
comment
@masfenix рад, что вы это поняли, я также обновил свой ответ, включив в него динамическую версию sql, если она вам нужна. - person Taryn; 02.11.2012