Это даст точный результат, который вы описали, и вы можете добавить больше столбцов, если необходимо
DECLARE @a table (id char, cola varchar(10))
DECLARE @b table (id char, detail_id int, colx char(3), coly char(3))
INSERT @a values('A', 'value1'),('B', 'value2'),('C','value3')
INSERT @b values('A', 0, 'foo', 'foo'),('A', 1, 'bar', 'bar'),
('B',0, 'foo','foo')--,('A', 2, 'bar', 'bar') -- add this for extra columns
CREATE TABLE ##t(id char, detail_id tinyint, colvalue char(3), col varchar(8), cola varchar(10))
DECLARE @columns varchar(max)=''
DECLARE @sqlstring varchar(1000)
;WITH a as (
SELECT a.id, a.cola, b.detail_id, colx, coly,
'col_x_' + cast(detail_id as varchar) col_a,
'col_y_' + cast(detail_id as varchar) col_b
FROM @a a LEFT JOIN @b b on a.id = b.id
)
INSERT ##t
SELECT id, detail_id, colx, col_a, cola FROM a
UNION
SELECT id, detail_id, coly, col_b, cola FROM a
ORDER BY 4,2
SELECT @columns = coalesce(@columns, '') +',[' + col + ']'
FROM (
SELECT DISTINCT col, detail_id FROM ##t where not col is null
) a
SET @columns = stuff(@columns, 1,1,'')
SET @sqlstring =
'SELECT * FROM (
SELECT id, cola, col, colvalue FROM ##t
) b
PIVOT(max(colvalue) FOR col
in(
'+@columns+'))AS p order by 1'
EXEC(@sqlstring)
DROP TABLE ##t