动态创建的 key/value 对上的 PIVOT 和 INNER JOIN

PIVOT and INNER JOIN on dynamically created key/value pairs

在我的数据库中,我有一些产品。这些产品有数量未知的 parameters/fields 作为名称和值存储在单独的 table.

http://sqlfiddle.com/#!18/f3b3e

CREATE TABLE Products
    ([ProductId] varchar(50), [Name] varchar(50))
;
    
INSERT INTO Products
    ([ProductId], [Name])
VALUES
    ('PROD1', 'Product 1'),
    ('PROD2', 'Product 2'),
    ('PROD3', 'Product 3')
;

CREATE TABLE ProductFields
    ([ProductId] varchar(50), [Name] varchar(50), [Value] varchar(50))
;
    
INSERT INTO ProductFields
    ([ProductId], [Name], [Value])
VALUES
    ('PROD1', 'Color', 'Red'),
    ('PROD1', 'Size', '2'),
    ('PROD1', 'Weight', '50'),
    ('PROD2', 'Color', 'Blue'),
    ('PROD2', 'Size', '1'),
    ('PROD2', 'Weight', '15'),
    ('PROD3', 'Color', 'Yellow'),
    ('PROD3', 'Size', '3'),
    ('PROD3', 'Weight', '10')
;

如果我有 3 个产品,我希望我的输出包含 3 行,如下所示:

ProductId   Name        Color     Size     Weight
----------- ----------- --------- -------- ---------
PROD1       Product 1   Red       2        50
PROD2       Product 2   Blue      1        15
PROD3       Product 3   Yellow    3        10

如何创建一个动态 PIVOT,该 PIVOT 也具有针对另一个 table 的 INNER JOIN?所有的值都很好而且只是 VARCHAR,所以这应该很容易,但是,我不能把我的头围在具有动态值的 PIVOT 上。

这是我的做法:

DECLARE 
@cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX);

SET @cols = STUFF((SELECT distinct ',' + QUOTENAME(pf.Name) 
            FROM ProductFields pf
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

SET @query = 'SELECT p.ProductId, p.Name, ' + @cols + ' from 
            (
                SELECT p.ProductId, p.Name FROM Products p
                INNER JOIN ProductFields pf
                ON pf.ProductId = p.ProductId
           ) x
            pivot 
            (
                Value
                for Name in (' + @cols + ')
            ) pi '


execute(@query)

也许这会有所帮助。注意包含 ITEMmax(Value)

示例或dbFiddle

DECLARE 
@cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX);

SET @cols = STUFF((SELECT distinct ',' + QUOTENAME(pf.Name) 
            FROM ProductFields pf
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')


SET @query = 'SELECT * 
                from (
                       SELECT p.ProductId
                             ,p.Name
                             ,Item=pf.Name
                             ,pf.Value 
                         FROM Products p
                         JOIN ProductFields pf
                           ON pf.ProductId = p.ProductId
                     ) x
            pivot 
            (
                max(Value)
                for Item in (' + @cols + ')
            ) pi '


execute(@query)