1

I'm stuck on using PIVOT in a simple example (which I give in entirety below). Full disclosure, I got this from https://www.hackerrank.com/. I picked it precisely because I want to get more familiar with PIVOT and this looked like a simple example! I've looked at numerous posts on the subject, and have been using this to crib off: https://social.msdn.microsoft.com/Forums/sqlserver/en-US/b76a4668-d0c3-4c51-8d86-117d5c181e69/pivot-without-aggregate-function?forum=transactsql but don't seem to be able to get things quite right. Here is the table:

 TABLE OCCUPATIONS

Name    Occupation
Samantha    Doctor
Julia   Actor
Maria   Actor
Meera   Singer
Ashley  Professor
Ketty   Professor
Christeen   Professor
Jane    Actor
Jenny   Doctor
Priya   Singer

The task is to have the output with columns Doctor, Professor, Singer or Actor (in that order). If you run out of data for one or more columns, put NULL. Here is the expected output (copied directly from the site).

Jenny    Ashley     Meera  Jane
Samantha Christeen  Priya  Julia
NULL     Ketty      NULL   Maria

As an aside, it appears they want the results without column headers (I'm not sure!).

Here is the latest iteration of what I have tried:

SELECT [Doctor], [Professor],[Singer], [Actor]
FROM
(SELECT [Name], [Occupation] from OCCUPATIONS) as pvtsource
PIVOT
( MAX([Name]) FOR [Occupation] IN ([Doctor], [Professor],[Singer], [Actor]) ) AS p

and it yields:

     Doctor Professor   Singer  Actor
Samantha    Ketty   Priya   Maria

I'm not surprised by this incorrect result. After all, I did say in my query MAX. I assume it's just picking the MAX name for each profession based on the alphabetical sort. Maria is a "bigger" actor than Julia or Jane for example if you based it on the alphabet. But when I remove the MAX, I get an error ("Incorrect syntax..."). How does one do this?

Thanks! Bonus questions 1. Good, gentle, articles to PIVOT? I clearly haven't gotten it through my thick head. Eventually, I do want to be able to do more complicated pivots where I SUM or take MAX. 2. How to display results without column headers? 3. I'd also be interested in how to do this without PIVOT if there is a simple way.

sacse
  • 3,634
  • 2
  • 15
  • 24
Dave
  • 8,095
  • 14
  • 56
  • 99
  • Pivoting *is* a form of aggregation. – Thom A Mar 10 '20 at 15:55
  • Does this answer your question? [TSQL Pivot without aggregate function](https://stackoverflow.com/q/1343145/2029983). Personally, i suggest the Conditional Aggregate/"Cross-tab" [answer](https://stackoverflow.com/a/1343174/2029983). – Thom A Mar 10 '20 at 15:56
  • @Larnu. I saw that link before. Either it doesn't answer my question, or I'm too dense to see it. The accepted answer talks about using "MAX", and as I mention I get the wrong result when using MAX (or MIN). – Dave Mar 10 '20 at 16:03

1 Answers1

2

You need to "FEED" the pivot with an X-Axis,Y-Axis and a Value. We create a row key via dense_rank()

Example

Declare @YourTable Table ([Name] varchar(50),[Occupation] varchar(50))  Insert Into @YourTable Values 
 ('Samantha','Doctor')
,('Julia','Actor')
,('Maria','Actor')
,('Meera','Singer')
,('Ashley','Professor')
,('Ketty','Professor')
,('Christeen','Professor')
,('Jane','Actor')
,('Jenny','Doctor')
,('Priya','Singer')

Select * 
 from (Select *
             ,RN = dense_rank() over (partition by occupation order by name)
        From  @YourTable
      ) src
 Pivot (max(Name) for Occupation in ([Doctor], [Professor],[Singer], [Actor]) ) pvt 

Returns

RN  Doctor      Professor   Singer  Actor
1   Jenny       Ashley      Meera   Jane
2   Samantha    Christeen   Priya   Julia
3   NULL        Ketty       NULL    Maria

NOTE:

If you don't want RN in your results, rather than the top SELECT *, you can specify the desired columns

SELECT [Doctor], [Professor],[Singer], [Actor]
 From  (...) src
 Pivot (...) pvt

EDIT - Commentary

If you run the inner query

Select *
      ,RN = dense_rank() over (partition by occupation order by name)
 From  @YourTable
 Order By RN

You'll get

Name        Occupation  RN
Jane        Actor       1
Jenny       Doctor      1
Ashley      Professor   1
Meera       Singer      1
Priya       Singer      2
Christeen   Professor   2
Samantha    Doctor      2
Julia       Actor       2
Maria       Actor       3
Ketty       Professor   3

RN becomes the Y-Axis, Occupation becomes the X-Axis and Name is the value. Pivots by design are aggregates, therefore we just need a Y-Axis to perform the group by.

John Cappelletti
  • 79,615
  • 7
  • 44
  • 66
  • Thank you @john-cappelletti ! That seems to work. I need to study what is going on as I want to understand it, not just have a working solution. I've never seen dense_rank before, and am unfamiliar with the "partition by occupation order by name". Most importantly, I don't understand how doing this made it so you could use "max", because clearly you still use max. Could you leave a few comments on your answer about that? Thanks a million. – Dave Mar 10 '20 at 16:09
  • 1
    @Dave fyi row_number() will work as well. Dense_Rank will compress dupes – John Cappelletti Mar 10 '20 at 16:20
  • Thank you very much for the answer and the additional explanation! It's still a little shaky in my head (I don't use SQL all the time)* but you've given me more than enough to study and learn from. If you have any favorite PIVOT tutorials/articles, send them my way! Thanks! *Mostly I"m still trying to get my head around how all this allows MAX to be used without problems. – Dave Mar 10 '20 at 16:25
  • 1
    @Dave With regards to Tutorials, I'm sorry that I won't be much help there. When I have questions (which is often), my first stop is SO. Regarding the ,RN = ... this is just a style I've adopted. Easier to read and comment out for debugging. I HATE the {expression} as Column_Name format. Reading a long expression just to find out that it is not the object of interest. On the other hand, Gordon Linoff hates my formatting. At the end of the day, it is what works best for you. Keep learning and asking if there is a better way :) – John Cappelletti Mar 10 '20 at 16:33