Что было бы хорошим способом развернуть эти данные? - PullRequest
2 голосов
/ 24 мая 2019

У меня есть данные в следующей гранулярности:

CityID | Name | Post_Science | Post_Science | Post_Reading | Pre_Reading | Post_Writing | Pre_Writing  
123    | Bob  | 2.0          | 1.0          |     2.0      |    4.0      |     1.0      | 1.0

Я буду называть эти <Post/Pre>_XXXXXX столбцы метками.По сути, эти имена столбцов без текстовой карты «Pre» или «Post» соответствуют метке в другой таблице.

Я хочу повернуть данные таким образом, чтобы значения pre и postодна и та же метка находится в одной строке для каждой группы CityID, Name, Label.Так это будет выглядеть так:

CityID | Name | Pre Category | Post Category | Label 
123    | Bob  | 1.0          |     2.0       | Science
123    | Bob  | 4.0          |     2.0       | Reading
123    | Bob  | 1.0          |     1.0       | Writing

Label приходит из отдельной таблицы через соединение.Надеюсь, это никого не смущает.Если это так, игнорируйте этот столбец.

Так что этих категорий гораздо больше - Наука, Чтение и Письмо - вот лишь некоторые из тех, что я выбрал, например.

Я думал о двух вариантах получения данных в этом формате:

  1. Отключение всех данных в длинный список всех значений в группе CityID, Name, Label.Затем разберите имя Label и поверните обратно в значения pre и post одной категории в 1 строку
  2. Сделайте кучу Union s.Поэтому выберите все науки в одном select утверждении, все Reading в другом утверждении и объедините их.Существует около 50 пар, поэтому 50 операторов объединения

Я представляю, что первый вариант чище, чем второй.Есть ли другие варианты?

Ответы [ 2 ]

3 голосов
/ 24 мая 2019

Это Отключение , и я настоятельно рекомендую apply:

select t.CityId, t.Name, v.*
from t cross apply
     (values (t.Post_Science, t.Pre_Science, 'Science'),
             (t.Post_Reading, t.Pre_Reading, 'Reading'),
             (t.Post_Writing, t.Pre_Writing, 'Writing')
     ) v(postcategory, precategory, label) ;

UNPIVOT - это очень специфический синтаксис для выполнения одной вещи. APPLY вводит боковые соединения, которые очень эффективны для этой и многих других целей.

2 голосов
/ 24 мая 2019

Понятно, что решение Гордона было бы более производительным, но если у вас есть МНОГИЕ или ПЕРЕМЕННЫЕ КОЛОННЫ , здесь есть опция, которая динамически ОТВЕРЖИТ ваши данные без фактического использования DYNAMIC SQL

Пример

Select A.CityID
      ,A.Name
      ,PreCat  = max(case when Item Like 'Pre%'  then Value end)
      ,PostCat = max(case when Item Like 'Post%' then Value end)
      ,Label   = substring(Item,charindex('_',Item+'_')+1,50)
 From  YourTable A
 Cross Apply ( values (cast((Select A.* for XML RAW) as xml))) B(XMLData)
 Cross Apply (
                Select Item  = xAttr.value('local-name(.)', 'varchar(100)')
                      ,Value = xAttr.value('.','varchar(max)')
                 From  XMLData.nodes('//@*') xNode(xAttr)
                 Where xAttr.value('local-name(.)','varchar(100)') not in ('CityId','Name','Other-Columns','To-Exclude')
             ) C
 Group By A.CityID
         ,A.Name
         ,substring(Item,charindex('_',Item+'_')+1,50)

Возвращает

CityID  Name    PreCat  PostCat Label
123     Bob     4.0     2.0     Reading
123     Bob     1.0     2.0     Science
123     Bob     1.0     1.0     Writing
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...