You can try to use Condition Aggregate function, MAX
with CASE WHEN
and GROUP BY
CREATE TABLE [Book] (
[Id] int
);
INSERT INTO [Book] ([Id])
VALUES (1);
INSERT INTO [Book] ([Id])
VALUES (2);
INSERT INTO [Book] ([Id])
VALUES (3);
INSERT INTO [Book] ([Id])
VALUES (4);
CREATE TABLE [BookProperty] (
[Name] VARCHAR(100),
[Value] VARCHAR(100),
[BookId] int
);
INSERT INTO [BookProperty] ([Name], [Value], [bookId])
VALUES ('Author', 'Robert', 1);
INSERT INTO [BookProperty] ([Name], [Value], [bookId])
VALUES ('Author', 'Tim', 2);
INSERT INTO [BookProperty] ([Name], [Value], [bookId])
VALUES ('PublishedYear', '2018', 3);
INSERT INTO [BookProperty] ([Name], [Value], [bookId])
VALUES ('PublishedYear', '2017', 1);
INSERT INTO [BookProperty] ([Name], [Value], [bookId])
VALUES ('Title', 'Winning', 4);
Query 1:
SELECT id,
MAX(CASE WHEN Name = 'Author' THEN Value END) as 'Author',
MAX(CASE WHEN Name = 'PublishedYear' THEN Value END) as 'PublishedYear',
MAX(CASE WHEN Name = 'Title' THEN Value END) as 'Title'
FROM [Book] b INNER JOIN [BookProperty] bp
on b.Id = bp.BookId
GROUP BY id
Results:
| id | Author | PublishedYear | Title |
|----|--------|---------------|---------|
| 1 | Robert | 2017 | (null) |
| 2 | Tim | (null) | (null) |
| 3 | (null) | 2018 | (null) |
| 4 | (null) | (null) | Winning |
EDIT
You can try to use dynamic pivot to make you expect.
use STUFF
function dynamic create Condition Aggregate function execute statement then use execute dynamic excute your sql.
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX);
SET @cols = STUFF((SELECT DISTINCT ',MAX(CASE WHEN Name = ''' + Name +''' THEN [Value] END) as ''' + Name + ''' '
FROM [Book] b INNER JOIN [BookProperty] bp
on b.Id = bp.BookId
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT ID, '+ @cols + ' FROM [Book] b INNER JOIN [BookProperty] bp on b.Id = bp.BookId GROUP BY id'
execute(@query)