Search code examples
sqlsql-serversql-server-2008unpivot

SQL: UN-PIVOT and separate by individual score


I am using SQL Server 2008 and am trying to write a query that splits columns into individual rows. I am pulling count data and need to transform it into individual scores.

Example:
5 students answer ‘always’ and an answer of ‘always’ = 3 points;
4 students answer ‘usually’ and answer of ‘usually’ = 2 points

Instead of having a field named ‘always’ with a count of 5 and a field named ‘usually’ with a count of 4, I would like to have one field named ‘Score’ with 5 rows of 3 and 4 rows of 2.

I have started my query by using an UNPIVOT, however, it does not split the data as described. I have included sample data and my desired results below. Any help would be appreciated.

Always = 3 points  
Usually = 2 points      
Sometimes = 1 points    
Never = 0 points 

Sample Data:

CREATE TABLE #TEST(QUESTION VARCHAR(15), STUDENT VARCHAR(15), STARTDATE DATE, ALWAYS INT, USUALLY INT, SOMETIMES INT, NEVER INT)

INSERT #TEST(QUESTION, STUDENT, STARTDATE, ALWAYS, USUALLY, SOMETIMES, NEVER)
VALUES
('A','BOB','01/01/2016',2,1,1,2),
('A','BOB','03/01/2016',3,1,1,0),
('A','JIM','01/01/2016',2,1,2,0),
('A','JIM','03/01/2016',4,1,0,0),
('BB','BOB','03/01/2016',2,1,1,2),
('BB','BOB','07/01/2016',3,1,1,0),
('BB','JIM','03/01/2016',2,1,2,0),
('BB','JIM','07/01/2016',4,1,0,0)  

Query:

WITH A AS (
    SELECT *
    FROM #TEST
    --WHERE 
    --  QUESTION = 'A' 
    --AND STUDENT IN ('BOB','JIM')
    --AND STARTDATE = '2016-01-01'
)   
SELECT QUESTION, STUDENT, STARTDATE, SCORE
FROM 
    (   SELECT QUESTION, STUDENT, STARTDATE, ALWAYS, USUALLY, SOMETIMES, NEVER
        FROM A
    ) P
UNPIVOT
    ( SCORE FOR Z IN (ALWAYS, USUALLY, SOMETIMES, NEVER)
    ) AS unpvt  

Expected Results: for 1st 2 rows

QUESTION|STUDENT|STARTDATE|SCORE|
--------+-------+---------+-----+
A       |BOB    |1/1/2016 |3    |--ALWAYS
A       |BOB    |1/1/2016 |3    |--ALWAYS
A       |BOB    |1/1/2016 |2    |--USUALLY
A       |BOB    |1/1/2016 |1    |--SOMETIMES
A       |BOB    |1/1/2016 |0    |--NEVER
A       |BOB    |1/1/2016 |0    |--NEVER
A       |BOB    |3/1/2016 |3    |--ALWAYS
A       |BOB    |3/1/2016 |3    |--ALWAYS
A       |BOB    |3/1/2016 |3    |--ALWAYS
A       |BOB    |3/1/2016 |2    |--USUALLY
A       |BOB    |3/1/2016 |1    |--SOMETIMES

Solution

  • With the help of a CROSS APPLY and an ad-hoc tally table

    Select A.Question
          ,A.Student
          ,A.StartDate
          ,B.Score
     From  #Test A
     Cross Apply ( values (Always,3)
                         ,(Usually,2)
                         ,(Sometimes,1)
                         ,(Never,0) 
                  ) B(Cnt,Score)
     Join (Select Top 100 N=Row_Number() Over (Order By Number) From master..spt_values ) C
       on (C.N <= B.Cnt)
     Where Student='Bob' and question ='A'
    

    Returns

    Question    Student StartDate   Score
    A           BOB     2016-01-01  3
    A           BOB     2016-01-01  3
    A           BOB     2016-01-01  2
    A           BOB     2016-01-01  1
    A           BOB     2016-01-01  0
    A           BOB     2016-01-01  0
    A           BOB     2016-03-01  3
    A           BOB     2016-03-01  3
    A           BOB     2016-03-01  3
    A           BOB     2016-03-01  2
    A           BOB     2016-03-01  1