【问题标题】:PIVOT and INNER JOIN on dynamically created key/value pairs动态创建的键/值对上的 PIVOT 和 INNER JOIN
【发布时间】:2021-04-15 14:42:15
【问题描述】:

在我的数据库中,我有一些产品。这些产品有数量不详的参数/字段,以名称和值的形式存储在单独的表中。

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 也具有针对该其他表的 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)

【问题讨论】:

  • 真的需要修正你的设计;这才是真正的问题。
  • 这能回答你的问题吗? (SQL Server dynamic PIVOT query?
  • @Larnu 没有,因为没有 JOIN。我试过了,但无法实现 JOIN。
  • 然后将连接放入动态 SQL 中。仅仅因为它没有加入并不意味着不回答它。
  • @Larnu 是的,我只是举个例子。这不是现实世界中的样子,但肯定有一个表包含一个键/值对参数:-)

标签: sql-server pivot inner-join


【解决方案1】:

也许这会有所帮助。注意 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)

【讨论】:

  • 感谢您的回复 - dbFiddle 的结果正是我想要的。不知道为什么我在 SQLFiddle 上得到Must declare the scalar variable "@cols",但你得到的似乎有效!谢谢你:)
  • @MortenMoulder 总是乐于提供帮助。
  • @MortenMoulder 如果您的 SQL Server 版本上有 STRING_AGG,则应该使用它而不是 FOR XML
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-14
  • 1970-01-01
  • 2023-03-08
  • 2021-11-21
  • 2020-03-01
  • 1970-01-01
相关资源
最近更新 更多