Возможно ли развернуть несколько столбцов TSQL с именованными строками?

Я знаю, что здесь есть несколько дискуссий о развороте/перекрестном применении, но мне не удалось найти ни одной дискуссии, посвященной моей проблеме. На данный момент у меня есть следующее:

SELECT Perc, Salary
FROM (
    SELECT jobid, Salary_10 AS Perc10, Salary_25 AS Perc25, [Salary_Median] AS Median
    FROM vCalculatedView
    WHERE JobID = '1'
    GROUP BY JobID, SourceID, Salary_10, Salary_25, [Salary_Median]
) a
UNPIVOT (
    Salary FOR Perc IN (Perc10, Perc25, Median)
) AS calc1

Теперь я хотел бы добавить несколько других столбцов, например. один с именем Bonus, который я также хочу поместить в Perc10, Perc25 и Median Rows.

В качестве альтернативы я также сделал запрос с перекрестным применением, но здесь кажется, что вы не можете «принудительно» отсортировать строки, как вы можете с помощью unpivot. Другими словами, у меня не может быть пользовательской сортировки, а только сортировка по номеру в таблице, если я прав? По крайней мере, здесь я получаю желаемый результат, но строки расположены в неправильном порядке, и у меня нет имен строк, таких как Perc10 и т. д., что было бы неплохо.

SELECT crossapplied.Salary,
       crossapplied.Bonus
FROM vCalculatedView v
CROSS APPLY (
    VALUES
          (Salary_10, Bonus_10)
        , (Salary_25, Bonus_25)
        , (Salary_Median, Bonus_Median)
) crossapplied (Salary, Bonus)
WHERE JobID = '1'
GROUP BY crossapplied.Salary,
         crossapplied.Bonus

Perc означает процентиль здесь.

Вывод должен быть примерно таким:

+--------------+---------+-------+
| Calculation  | Salary  | Bonus |
+--------------+---------+-------+
| Perc10       |      25 |     5 |
| Perc25       |      35 |    10 |
| Median       |      27 |     8 |
+--------------+---------+-------+

Я что-то пропустил или я что-то не так сделал? Я использую MSSQL 2014, вывод идет в SSRS. Большое спасибо за любую подсказку заранее!

Изменить для уточнения: метод Unpivot дает следующий результат:

    +--------------+---------+
    | Calculation  | Salary  |
    +--------------+---------+
    | Perc10       |      25 |
    | Perc25       |      35 |
    | Median       |      27 |
    +--------------+---------+

поэтому здесь отсутствует столбец «Бонус».

Метод Cross-Apply дает следующий результат:

+---------+-------+
| Salary  | Bonus |
+---------+-------+
|      35 |    10 |
|      25 |     5 |
|      27 |     8 |
+---------+-------+

Поэтому, если вы сравните его с предполагаемым результатом, вы заметите, что столбец «Расчет» отсутствует, а сортировка строк неверна (обратите внимание, что строка 25 | 5 находится во второй строке, а не в первой).

Правка 2: определение представления и образцы данных. Представление просто добавляет вычисляемые столбцы таблицы. В таблице у меня есть такие столбцы, как «Зарплата» и «Бонус» для каждого JobID. Затем представление просто вычисляет процентили следующим образом:

Select 
    Percentile_Cont(0.1)
    within group (order by Salary)
    over (partition by jobID) as Salary_10,

    Percentile_Cont(0.25)
    within group (order by Salary)
    over (partition by jobID) as Salary_25
from Tabelle

Таким образом, вывод выглядит следующим образом:

+----+-------+---------+-----------+-----------+
| ID | JobID | Salary  | Salary_10 | Salary_25 |
+----+-------+---------+-----------+-----------+
|  1 |     1 |     100 |        60 |        70 |
|  2 |     1 |     100 |        60 |        70 |
|  3 |     2 |     150 |        88 |       130 |
|  4 |     3 |      70 |        40 |        55 |
+----+-------+---------+-----------+-----------+

В конце представление будет параметризовано в хранимой процедуре.


person ksauter    schedule 22.03.2016    source источник
comment
Ваш vCalculatedView, кажется, выполняет расчеты заранее... Ваш group by ничего не делает... Пожалуйста, покажите результат, который вы получаете в своем заявлении, и предоставьте некоторые примерные данные и ожидаемый результат.   -  person Shnugo    schedule 22.03.2016
comment
Группа by в коде Cross Apply что-то делает: если бы я не вставил ее, Perc10, Perc25, Median повторялись бы снова и снова. Это связано с тем, что идентификатор задания не является идентификатором сотрудника, и поэтому идентификатор задания может содержать более одного сотрудника.   -  person ksauter    schedule 22.03.2016
comment
ХОРОШО. Я понимаю что ты имеешь ввиду. Может быть, CTE с SELECT DISTINCT - это то, что вам нужно. GROUP BY вы бы использовали для агрегирования, например MAX() или SUM() Укажите результат вашего текущего запроса и способ отображения ваших данных.   -  person Shnugo    schedule 22.03.2016
comment
Спасибо за ваш ответ! Непонятно, о каком запросе вы здесь говорите. Вы имеете в виду Select Distinct к первому варианту (Unpivot) или ко второму (перекрестное применение)? Что касается вывода, моя маленькая таблица в конце поста показывает, что задумано и что дает unpivot — правда, без второго столбца. При перекрестном применении я получаю тот же результат, но без столбца «Расчет» и со всеми остальными столбцами (зарплата, бонус). Однако вывод здесь не отсортирован, поэтому, например. Perc25 выше Perc10, как указано выше в таблице.   -  person ksauter    schedule 22.03.2016
comment
Ах, я думаю, я только что понял, что вы имели в виду: вы ссылались на метод Cross Apply и хотели иметь предложение With, чтобы сослаться на него с таким именем, как T, и использовать его с Select * From T Group by... который затем оставляет вопрос: как мне получить столбец Calculation, с которым я мог бы сделать Order BY и CASE ?   -  person ksauter    schedule 22.03.2016
comment
Не могли бы вы предоставить образцы данных, которые выходят из вашего vCalculatedView? Определение VIEW также может помочь. Я не понимаю, до какого уровня там делается агрегация...   -  person Shnugo    schedule 22.03.2016
comment
Я только что понял, что забыл оператор where JobID = 1, который я исправил только что.   -  person ksauter    schedule 22.03.2016


Ответы (1)


Может быть, это ваш подход?

После ваших правок я понимаю, что ваше решение с CROSS APPLY вернется с правильными данными, но не с правильным выводом. Вы можете добавить постоянные значения в свой VALUES и выполнить сортировку в оболочке SELECT:

SELECT wrapped.Calculation,
       wrapped.Salary,
       wrapped.Bonus
FROM
(
    SELECT crossapplied.*
    FROM vCalculatedView v
    CROSS APPLY (
        VALUES
              (1,'Perc10',Salary_10, Bonus_10)
            , (2,'Perc25',Salary_25, Bonus_25)
            , (3,'Median',Salary_Median, Bonus_Median)
    ) crossapplied (SortOrder,Calculation,Salary, Bonus)
    WHERE JobID = '1'
    GROUP BY crossapplied.SortOrder,
             crossapplied.Calculation,
             crossapplied.Salary,
             crossapplied.Bonus
) AS wrapped
ORDER BY wrapped.SortOrder
person Shnugo    schedule 23.03.2016
comment
Благодарю вас! Я отметил ваше решение как правильное. Однако для других читателей вам нужно поместить все столбцы (SortOrder, Calculation, Salary, Bonus) в предложение GROUP BY, а не только Salary и Bonus. Прошлой ночью я написал запрос с помощью метода UNPIVOT с CTE и LEFT JOIN, но это, конечно, гораздо более длинный код. Для будущих читателей я добавлю это как еще один ответ, но это не превзойдет ваше решение. Ваши решения еще раз показывают, что в большинстве случаев CROSS APPLY превосходит Unpivot, как показывают многочисленные сравнения блоггеров. - person ksauter; 23.03.2016
comment
Спасибо за принятие! Я отредактировал свой ответ, чтобы отразить ваш намек на GROUP BY COLUMNS. Если вам нравится мой ответ, было бы неплохо дополнительно проголосовать за него. Голосование и принятие — это два отдельных шага… Еще раз спасибо! - person Shnugo; 23.03.2016