Reputation: 857
I'm pretty bad at explaining, so I'll try and let my examples do most of the talking. Let's say I have a table like so:
dbo.ExampleTable
===================================
ID Year Data1 Data2
====== ======== ========= =========
12 2016 FOO BAR
13 2016 FOO MAN
14 2016 SAW BAR
20 2017 FOO BAR
21 2017 FOO MAN
27 2017 SAW BAR
29 2017 CHU CAR
44 9999 FOO BAR
48 9999 FOO MAN
51 9999 SAW BAR
52 9999 CHU CAR
Some notes:
I want to create a table from that data that looks like this:
ID_9999 ID_2016 ID_2017
=========== =========== ===========
44 12 20
48 13 21
51 14 27
52 NULL 29
So essentially, for every unique pairing of Data1 and Data2 where Year=9999, I want to create a row which contains the ID of that pairing where Year=9999, as well as the ID for the pairings where Year=2016 and also Year=2017. Additionally, if either 2016 or 2017 do not containing that Data pairing, I want their value as NULL.
This is the query I've got so far:
SELECT tbl9999.ID ID_9999,
tbl2016.ID ID_2016,
tbl2017.ID ID_2017
FROM dbo.ExampleTable tbl9999
LEFT JOIN dbo.ExampleTable tbl2016
ON tbl9999.Data1 = tbl2016.Data1
AND tbl9999.Data2 = tbl2016.Data2
LEFT JOIN dbo.ExampleTable tbl2017
ON tbl9999.Data1 = tbl2017.Data1
AND tbl9999.Data2 = tbl2017.Data2
WHERE tbl9999.Year=9999
AND tbl2016.Year=2016
AND tbl2017.Year=2017
This seems to work mostly fine, however it will generate a table like this:
ID_9999 ID_2016 ID_2017
=========== =========== ===========
44 12 20
48 13 21
51 14 27
*Notice that it's missing the row with the null value in my example above. Is there any way to change my query to include that null value such that I have it in my example?
Please let me know if I'm missing any information or need anything clarified. Thanks in advance!
EDIT: I was able to find an answer on my own! This is the code I used to achieve my desired result:
SELECT [9999] [ID_9999],
[2016] [ID_2016],
[2017] [ID_2017]
FROM dbo.ExampleTable
PIVOT (MAX([ID]) FOR [Year] IN ([2016],[2017],[9999])) [x]
ORDER BY ID_9999
Upvotes: 2
Views: 435
Reputation: 1269633
You can do this in multiple ways. Conditional aggregation seems simple enough:
select max(case when year = 2016 then id end) as id_2016,
max(case when year = 2017 then id end) as id_2017,
max(case when year = 9999 then id end) as id_9999
from (select t.*, row_number() over (partition by year order by id) as seqnum
from dbo.ExampleTable t
) t
group by seqnum
order by seqnum;
Upvotes: 3