I've been trying to wrap my feeble mind around this one for some time, but I am having difficulty. I have looked at a few other examples like this SE.DBA answer, but I am having difficulty applying it to my exact situation. I do not care if the solution uses PIVOT/UNPIVOT or Cross Apply.
I am using GROUP BY because there are maybe 15-45 records per payroll, and I want all those records summed up per payroll. I am using SQLServer 2016.
The DDL and data below show the source data and the PIVOT query that I currently have
--Source data table
CREATE TABLE #EmployeeTaxes
(
Employee int
,Payroll int
,FIT DECIMAL(19,2)
,Employee_FICA DECIMAL(19,2)
,Employer_FICA DECIMAL(19,2)
,Employee_MEDI DECIMAL(19,2)
,Employer_MEDI DECIMAL(19,2)
,FIT_Gross DECIMAL(19,2)
,Employee_FICA_Gross DECIMAL(19,2)
,Employer_FICA_Gross DECIMAL(19,2)
,Employee_MEDI_Gross DECIMAL(19,2)
,Employer_MEDI_Gross DECIMAL(19,2)
)
--Data in source table
INSERT INTO #EmployeeTaxes
VALUES (1, 1, 100.00, 150.00, 50.00, 200.00, 200.00, 20000.00, 20000.00, 20000.00, 20000.00, 20000.00)
,(2, 1, 100.00, 150.00, 50.00, 200.00, 200.00, 20000.00, 20000.00, 20000.00, 20000.00, 20000.00)
,(3, 1, 100.00, 150.00, 50.00, 200.00, 200.00, 20000.00, 20000.00, 20000.00, 20000.00, 20000.00)
,(1, 2, 200.00, 250.00, 150.00, 300.00, 300.00, 25000.00, 25000.00, 25000.00, 25000.00, 25000.00)
,(2, 2, 200.00, 250.00, 150.00, 300.00, 300.00, 25000.00, 25000.00, 25000.00, 25000.00, 25000.00)
,(3, 2, 200.00, 250.00, 150.00, 300.00, 300.00, 25000.00, 25000.00, 25000.00, 25000.00, 25000.00)
,(1, 3, 300.00, 350.00, 250.00, 400.00, 400.00, 30000.00, 30000.00, 30000.00, 30000.00, 30000.00)
,(2, 3, 300.00, 350.00, 250.00, 400.00, 400.00, 30000.00, 30000.00, 30000.00, 30000.00, 30000.00)
,(3, 3, 300.00, 350.00, 250.00, 400.00, 400.00, 30000.00, 30000.00, 30000.00, 30000.00, 30000.00)
--Basic data layout as it currently is
SELECT PAYROLL
,sum(fit) AS SumFIT
,sum(fit_gross) AS SumFIT_Gross
,sum(employee_fica) AS Sum_EE_FICA
,sum(employee_fica_gross) AS Sum_EE_FICA_Gross
,sum(employer_fica) AS Sum_ER_FICA
,sum(employer_fica_gross) AS Sum_ER_FICA_Gross
,sum(employee_medi) AS Sum_EE_Medi
,sum(employee_medi_gross) AS Sum_EE_Medi_Gross
,sum(employer_medi) AS Sum_ER_Medi
,sum(employer_medi_gross) AS Sum_ER_Medi_Gross
FROM #EmployeeTaxes
GROUP BY Payroll
--The query as I have it now, missing the Gross column
SELECT PAYROLL
,[Taxes]
,[Tax]
FROM
(
SELECT PAYROLL
,sum(fit) AS SumFIT
,sum(fit_gross) AS SumFIT_Gross
,sum(employee_fica) AS Sum_EE_FICA
,sum(employee_fica_gross) AS Sum_EE_FICA_Gross
,sum(employer_fica) AS Sum_ER_FICA
,sum(employer_fica_gross) AS Sum_ER_FICA_Gross
,sum(employee_medi) AS Sum_EE_Medi
,sum(employee_medi_gross) AS Sum_EE_Medi_Gross
,sum(employer_medi) AS Sum_ER_Medi
,sum(employer_medi_gross) AS Sum_ER_Medi_Gross
FROM #EmployeeTaxes
GROUP BY Payroll
) CK
UNPIVOT
(
Tax FOR Taxes IN (SumFIT
,Sum_EE_FICA
,Sum_ER_FICA
,Sum_EE_Medi
,Sum_ER_Medi)
) AS Unpvt
ORDER BY PAYROLL
DROP TABLE #EmployeeTaxes
What I want to do is have the columns that are marked with "_gross" on the end to be in their own separate column as shown by the fake data below
--Fake table that holds structure of desired output
CREATE TABLE #FakeDesiredOutput
(
Payroll int
,Witholding varchar(100)
,Tax DECIMAL(19,2)
,Gross DECIMAL(19,2)
)
INSERT INTO #FakeDesiredOutput
VALUES (1,'FIT', 300.00, 60000.00)
,(1,'Employee_FICA', 450.00, 60000.00)
,(1,'Employer_FICA', 150.00, 60000.00)
,(1,'Employee_MEDI', 600.00, 60000.00)
,(1,'Employer_MEDI', 600.00, 60000.00)
,(2,'FIT', 600.00, 75000.00)
,(2,'Employee_FICA', 750.00, 75000.00)
,(2,'Employer_FICA', 450.00, 75000.00)
,(2,'Employee_MEDI', 900.00, 75000.00)
,(2,'Employer_MEDI', 900.00, 75000.00)
,(3,'FIT', 900.00, 90000.00)
,(3,'Employee_FICA', 1050.00, 90000.00)
,(3,'Employer_FICA', 750.00, 90000.00)
,(3,'Employee_MEDI', 1200.00, 90000.00)
,(3,'Employer_MEDI', 1200.00, 90000.00)
SELECT * FROM #FakeDesiredOutput
DROP TABLE #FakeDesiredOutput
Best Answer
The
CROSS APPLY
way of doing this would be:The results:
The
CROSS APPLY
clause has a fourth column,OrderByNum
simply to allow the results to reflect your desired sort order, whereFIT
comes before the other entries.