#sql #sql-server #sql-server-2008 #pivot
#sql #sql-сервер #sql-server-2008 #сводная
Вопрос:
Я уже 3 дня бьюсь головой об стену по этому поводу, поэтому надеюсь, что кто-нибудь сможет мне помочь.
У меня есть набор данных, к которым мне нужно выполнить некоторый поворот, но я не могу понять синтаксис.
Образец набора данных:
Employee LastName FirstName Status Location GroupBU DeductionDesc Active Field Value
----------------------------------------------------------------------------------------------------------------------------------
12345 SMITH JOHN A 5555 9999 LIFE INS CHILD Y Deduction 8502
12345 SMITH JOHN A 5555 9999 LIFE INS CHILD Y EmployeeAmtPct 0.1
12345 SMITH JOHN A 5555 9999 LIFE INS CHILD Y EmployeeAnnSalary 10000
12345 SMITH JOHN A 5555 9999 LIFE INS CHILD Y EmployeeInsAmt 10000
67890 SMITH JANE A 5555 9999 LIFE INS SPOUSE Y Deduction 8501
67890 SMITH JANE A 5555 9999 LIFE INS SPOUSE Y EmployeeAmtPct 0.357
67890 SMITH JANE A 5555 9999 LIFE INS SPOUSE Y EmployeeAnnSalary 50000
67890 SMITH JANE A 5555 9999 LIFE INS SPOUSE Y EmployeeInsAmt 50000
Желаемый результат:
Employee LastName FirstName Status Location GroupBU [LIFE INS CHILD] Deduction EmployeeAmtPct EmployeeAnnSalary EmployeeInsAmt [LIFE INS SPOUSE] Deduction EmployeeAmtPct EmployeeAnnSalary EmployeeInsAmt
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
12345 SMITH JOHN A 5555 9999 LIFE INS CHILD 8502 0.1 10000 10000 NULL NULL NULL NULL NULL
67890 SMITH JANE A 5555 9999 NULL NULL NULL NULL NULL LIFE INS SPOUSE 8501 0.357 50000 50000
Очевидно, что в моем «желаемом результате» у меня есть повторяющиеся имена столбцов, которые не будут работать, поэтому я предполагаю, что мне нужно будет придумать способ добавления / добавления чего-либо к каждому из них, чтобы сделать их уникальными, но я не смог понять, как это сделатьэто. Это также было бы необходимо, чтобы связать различные поля и значения с соответствующим «DeductionDesc» в окончательном выводе. Также было запрошено, чтобы значение в «DeductionDesc» было именем столбца в окончательном выводе, и если значение не существует, оно просто равно NULL (показано в выводе).
Мои исходные данные были созданы с использованием UNPIVOT, поскольку кажется, что это повысит вероятность успеха.
У меня около 65 уникальных значений в «DeductionDesc» и около 3500 уникальных записей о сотрудниках.
Вот текущая (и примерно 4-я итерация) кода, который у меня есть:
select *
from
(
select Employee,LastName,FirstName,Status,Location,GroupBU,DeductionDesc,Active,Field,Value
FROM MyTable
) unpvt
PIVOT
(
MAX([DeductionDesc])
FOR [DeductionDesc] IN ([LIFE INS SPOUSE],[LIFE INS CHILD UNUM POST TAX])
) pvt
PIVOT
(
MAX([Value])
FOR [Field] IN ([InsPlan],[EmployeeAnnSalary],[InsCoverage],[InsEmployeeRate],[EmployeeAmtPct],[InsLevelDesc],[InsCoverageDesc],[InsCarrierDesc],[InsPlanDesc],[InsLevel],[Deduction],[EmployeeInsAmt],[InsCarrier])
) pvt
Для удобства чтения и упрощения я удалил большинство элементов из первого сводного элемента в операторе «IN», но изначально там были перечислены все 65.
Буду признателен за любую помощь, которую кто-либо может оказать, чтобы добиться желаемого результата. Если требуется дополнительная информация, пожалуйста, дайте мне знать. Спасибо!
Комментарии:
1. Какую версию SQL вы используете?
2. Я не вижу ПОВОРОТА в выводе вашего желания. Можете ли вы объяснить логику?
3. @Pat Это в SQL 2008 R2
4. @Juan Carlos Я пытаюсь повернуть столбец «DescriptionDesc» и сохранить связанные с ним другие столбцы рядом с ним. например, Вычет и различные столбцы «Rate» или «Amt» все еще находятся рядом с тем же DescriptionDesc, к которому они привязаны. Надеюсь, это имеет смысл (это также мой первый набег на PIVOT, и я просмотрел много других сообщений в поисках чего-то подобного)
5. Используйте оператор прецедента, это работа
Ответ №1:
Предполагая здесь синтаксис SQL Server, но концепция применима к большинству вариантов SQL. Один из способов атаковать это — использовать конструкцию CASE:
SELECT tA.Employee, tA.LastName, tA.FirstName, tA.Status, tA.Location,
tA.GroupBU, tB.Deduction, tB.EmployeeAmtPct
FROM your_table AS tA
INNER JOIN
(SELECT Employee, SUM(CASE WHEN Field = 'Deduction' THEN Value ELSE 0 END) AS Deduction,
SUM(CASE WHEN Field = 'EmployeeAmtPct' THEN Value ELSE 0 END) AS EmployeeAmtPct
...and so on for all the fields that you want to transpose...
FROM your_table
GROUP BY Employee) AS tB ON tA.Employee = tB.Employee
Я просто добавляю здесь вычеты и EmployeeAmtPct для краткости. По сути, это запрос с перекрестной таблицей. Он просто выполняет выборочное суммирование в зависимости от того, в какую категорию попадает «Поле». Предложение ELSE в операторе CASE гарантирует, что всегда есть значение для суммирования.
Комментарии:
1. Спасибо. Я тестирую это сейчас и подозревал, что потребуется ОБРАЩЕНИЕ / ОБЪЕДИНЕНИЕ. Сталкиваюсь с некоторыми проблемами преобразования, поэтому я устраню это и обновлю после завершения.
Ответ №2:
Если вы не возражаете перейти на динамический (измените #myTable на имя вашей таблицы)
Declare @SQL varchar(max) = ''
Select @SQL = @SQL SqlExpr
From (
Select Top 100 Percent *
,SqlExpr = case when ColNr=1 then char(13) ',' QuoteName(DeductionDesc) '=max(case when DeductionDesc=''' DeductionDesc ''' and Field=''' Field ''' then DeductionDesc else null end)' else '' end char(13) ',' QuoteName(Field) '=max(case when DeductionDesc=''' DeductionDesc ''' and Field=''' Field ''' then Value else null end)'
From (
Select Distinct
DeductionDesc
,Field
,ColNr = Row_Number() over (Partition By DeductionDesc Order By Field)
From #MyTable
) A Order By 1,3
) A
Select @SQL = '
Select Employee
,LastName
,FirstName
,Status
,Location
,GroupBU' @SQL '
From #MyTable
Group By
Employee
,LastName
,FirstName
,Status
,Location
,GroupBU
'
--Print(@SQL)
Exec(@SQL)
ВОЗВРАТ