You can use XML for this:
DECLARE @xml xml ;WITH patient_visit_codes AS ( SELECT * FROM (VALUES (1, 'B58B3850-43BB-434D-B1EA-B968A01332EA', '2015-12-22', '3018F', '2015-12-22 07:24:07.403'), (1, 'B58B3850-43BB-434D-B1EA-B968A01332EA', '2015-12-22', '1101F', '2015-12-22 07:28:09.440'), (56, '482A73F8-EA3F-4CD6-B1AD-BD2388EC5912', '2016-01-05', 'I50', '2016-01-05 11:05:34.830'), (56, '482A73F8-EA3F-4CD6-B1AD-BD2388EC5912', '2016-01-05', 'R50.90', '2016-01-05 11:35:14.560'), (56, '482A73F8-EA3F-4CD6-B1AD-BD2388EC5912', '2016-01-05', 'Z02.89', '2016-01-05 11:40:24.740') ) as t (pat_id, visit_id, visit_date, visit_code, create_timestamp)) , xml_t AS ( SELECT DISTINCT 1 as Tag, 0 as Parent, pat_id as [pat!1!id], visit_id as [pat!1!visit_id], NULL as [visit!2!visit_code] FROM patient_visit_codes UNION ALL SELECT DISTINCT 2 as Tag, 1 as Parent, pat_id as [pat!1!id], visit_id as [pat!1!visit_id], visit_code as [visit!2!visit_code] FROM patient_visit_codes) SELECT @xml = ( SELECT * FROM xml_t ORDER BY [pat!1!id], [pat!1!visit_id],[visit!2!visit_code] FOR XML EXPLICIT) --we get xml like that: --<pat id="1" visit_id="B58B3850-43BB-434D-B1EA-B968A01332EA"> -- <visit visit_code="1101F" /> -- <visit visit_code="3018F" /> --</pat> --<pat id="56" visit_id="482A73F8-EA3F-4CD6-B1AD-BD2388EC5912"> -- <visit visit_code="I50" /> -- <visit visit_code="R50.90" /> -- <visit visit_code="Z02.89" /> --</pat> SELECT Component.value('@id','int') as pat_id, Component.value('@visit_id','nvarchar(32)') as visit_id, Component.value('(visit/@visit_code)[1]','nvarchar(10)') as visit_code1, Component.value('(visit/@visit_code)[2]','nvarchar(10)') as visit_code2, Component.value('(visit/@visit_code)[3]','nvarchar(10)') as visit_code3, Component.value('(visit/@visit_code)[4]','nvarchar(10)') as visit_code4 FROM @xml.nodes('/pat') as X(Component)
and the result:
pat_id visit_id visit_code1 visit_code2 visit_code3 visit_code4 ----------- -------------------------------- ----------- ----------- ----------- ----------- 1 B58B3850-43BB-434D-B1EA-B968A013 1101F 3018F NULL NULL 56 482A73F8-EA3F-4CD6-B1AD-BD2388EC I50 R50.90 Z02.89 NULL (2 row(s) affected)