snowflake 的新手 - SQL 语句与连接和旋转值的问题

new to snowflake - issue with SQL statement with joins and pivoting values

我正在尝试通过将产品 table 链接到具有 3 个多对多 table

的特征 table 来建模产品

例如

从这个结构我试图回到一个结果来显示产品字段 characteristic.type characteristic.value 进入 select 语句。

例如:

select distinct 
    p.ProductId, p.name, p.description, p.brand, p.model, body, DoorNum
from    
    Product p
left join   
    ProductionCharacteristic pc on p.ProductId = pc.ProductId,
    (select CharacteristicId, "'Body'" as body, "'DoorNum'" as DoorNum  
     from Characteristic c
     pivot (max(c.name) for c.type IN ('Body' , 'DoorNum')))  temp
where  
    pc.CharacteristicId = temp.CharacteristicId

问题 1:any_Value 是聚合函数吗?它 pivot 不喜欢它,我正在使用 max() 代替 Issue2: 上面 select returns 3行。有没有办法把它压缩成一条记录?

备注

  1. 我必须坚持你 永远不要 使用混合连接表达式。这意味着,如果您要使用关键字 JOINLEFT JOIN ,则不要使用 ,,反之亦然。
  2. 你没有说清楚你期望的输出是什么样的,所以我将使用逗号分隔的列表,但也会展示你如何使用数组。
  3. 我将其作为评论放入,但值得重复:ANY_VALUE() 是一个聚合函数,但在 PIVOT 的上下文中不起作用 https://community.snowflake.com/s/question/0D50Z00008uVHTYSA4/anyvalue-does-not-work-on-pivot

查询选项

选项 1 - 内联数据透视(不推荐,因为它更难阅读并且数据透视子查询不能重复使用)

select 
    p.ProductId
    , p.name
    , p.description
    , p.brand
    , p.model
    , listagg(temp.body,', ') as body
    , listagg(temp.DoorNum,', ') as doornum1
    , arrayagg(temp.DoorNum) as doornum2
from    
    Product p
left join
    ProductionCharacteristic pc 
        on p.ProductId = pc.ProductId
join (
      select CharacteristicId, body, doornum
      from Characteristic c
      pivot (max(c.name) for c.type IN ('Body' , 'DoorNum')) as p (CharacteristicId, value, body, doornum)
    )  temp
    on pc.CharacteristicId = temp.CharacteristicId
group by 1,2,3,4,5
;

选项 2 - 以 CTE 为中心(推荐)

with temp as (
  select CharacteristicId, body, doornum
  from Characteristic c
  pivot (max(c.name) for c.type IN ('Body' , 'DoorNum')) as p (CharacteristicId, value, body, doornum)
)
select 
    p.ProductId
    , p.name
    , p.description
    , p.brand
    , p.model
    , listagg(temp.body,', ') as body
    , listagg(temp.DoorNum,', ') as doornum1
    , arrayagg(temp.DoorNum) as doornum2
from    
    Product p
left join
    ProductionCharacteristic pc 
        on p.ProductId = pc.ProductId
join temp
    on pc.CharacteristicId = temp.CharacteristicId
group by 1,2,3,4,5
;

选项 3 - 横向连接(类似于相关子查询)

select 
    p.ProductId
    , p.name
    , p.description
    , p.brand
    , p.model
    , temp.body
    , temp.doornum1
    , temp.doornum2
from    
    Product p
join lateral (
    select listagg(iff(type = 'Body',name,null),', ') as body
        ,listagg(iff(type = 'DoorNum',name,null),', ') as doornum1
        ,arrayagg(iff(type = 'DoorNum',name,null)) as doornum2
    from Characteristic c
    join ProductionCharacteristic pc 
            on pc.CharacteristicId = c.CharacteristicId
    where p.ProductId = pc.ProductId
    ) temp
;

希望对您有所帮助。