Home > Enterprise >  PIVOT using JOIN in SQL
PIVOT using JOIN in SQL

Time:10-13

I was asked to pivot this data using basic SQL and wasn't sure how to answer it. I googled some answers and realized you can use MAX or SUM with CASE expressions, but at the end of the interview I asked how you would solve the question and the interviewer said by using joins. Can anyone show me how it's done using joins?

BEGINNING TABLE

emp_id col_id col_desc attvalue month
1 1 salary 2000 2010-05-09
1 2 bonus 0 2010-05-09
1 3 compensation 2000 2010-05-09
1 1 salary 2000 2010-05-10
1 2 bonus 500 2010-05-10
1 3 compensation 2500 2010-05-10
2 1 salary 1000 2010-05-09
2 2 bonus 500 2010-05-09
2 3 compensation 1500 2010-05-09

Code to create the beginning table

CREATE TABLE Employees(emp_id INT, col_id INT, col_desc NVARCHAR(MAX), attvalue INT, month DATE);

INSERT INTO Employees
VALUES
(1,1,'salary',2000,'2010-05-09'),
(1,2,'bonus',0,'2010-05-09'),
(1,3,'compensation',2000,'2010-05-09'),
(1,1,'salary',2000,'2010-05-10'),
(1,2,'bonus',500,'2010-05-10'),
(1,3,'compensation',2500,'2010-05-10'),
(2,1,'salary',1000,'2010-05-09'),
(2,2,'bonus',500,'2010-05-09'),
(2,3,'compensation',1500,'2010-05-09');

RESULTING TABLE

emp_id month salary bonus compensation
1 2010-05-09 2000 0 2000
1 2010-05-10 2000 500 2500
2 2010-05-09 1000 500 1500

CodePudding user response:

Below are the self join, case expression and pivot way

-- Self Join way
select s.emp_id, s.month, 
       s.attvalue as salary,
       b.attvalue as bonus,
       c.attvalue as compensation
from   Employees s
       inner join Employees b on  s.emp_id   = b.emp_id
                             and  s.month    = b.month
       inner join Employees c on  s.emp_id   = c.emp_id
                             and  s.month    = c.month
where  s.col_desc = 'salary'
and    b.col_desc = 'bonus'
and    c.col_desc = 'compensation'
order by s.emp_id, s.month

-- case expression way
select emp_id, month,
       max(case when col_desc = 'salary' then attvalue else 0 end) as salary,
       max(case when col_desc = 'bonus'  then attvalue else 0 end) as bonus,
       max(case when col_desc = 'compensation' then attvalue else 0 end) as compensation
from   Employees
group by emp_id, month
order by emp_id, month

-- Pivot way
select *
from   (
           select emp_id, month, col_desc, attvalue
           from Employees
       ) d
       pivot
       (
           max(attvalue)
           for col_desc in ([salary], [bonus], [compensation])
       ) p
order by emp_id, month
  • Related