Я понимаю, что это два года, но меня беспокоит, что принятый ответ требует использования динамического SQL, и ответ с наибольшим количеством голосов не будет работать:
Select P.ProductId, P.Name
, Min( Case When PM.MetaKey = 'A' Then PM.MetaValue End ) As A
, Min( Case When PM.MetaKey = 'B' Then PM.MetaValue End ) As B
, Min( Case When PM.MetaKey = 'C' Then PM.MetaValue End ) As C
From Products As P
Join ProductMeta As PM
On PM.ProductId = P.ProductId
Group By P.ProductId, P.Name
Вы должны использовать Group By, иначе вы получите пораженный результат. Если вы используете Group By, вы должны обернуть каждый столбец, который отсутствует в предложении Group By, в статистическую функцию (или подзапрос).