snowflake 的新手 - SQL 语句与连接和旋转值的问题
new to snowflake - issue with SQL statement with joins and pivoting values
我正在尝试通过将产品 table 链接到具有 3 个多对多 table
的特征 table 来建模产品
例如
- 产品(productId、品牌、描述、型号)
- ProductCharacteristic (productId, characteristicId)
- 特征(characteristicId、类型、名称、值)
从这个结构我试图回到一个结果来显示产品字段 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行。有没有办法把它压缩成一条记录?
备注
- 我必须坚持你 永远不要 使用混合连接表达式。这意味着,如果您要使用关键字
JOIN
和 LEFT JOIN
,则不要使用 ,
,反之亦然。
- 你没有说清楚你期望的输出是什么样的,所以我将使用逗号分隔的列表,但也会展示你如何使用数组。
- 我将其作为评论放入,但值得重复: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
;
希望对您有所帮助。
我正在尝试通过将产品 table 链接到具有 3 个多对多 table
的特征 table 来建模产品例如
- 产品(productId、品牌、描述、型号)
- ProductCharacteristic (productId, characteristicId)
- 特征(characteristicId、类型、名称、值)
从这个结构我试图回到一个结果来显示产品字段 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行。有没有办法把它压缩成一条记录?
备注
- 我必须坚持你 永远不要 使用混合连接表达式。这意味着,如果您要使用关键字
JOIN
和LEFT JOIN
,则不要使用,
,反之亦然。 - 你没有说清楚你期望的输出是什么样的,所以我将使用逗号分隔的列表,但也会展示你如何使用数组。
- 我将其作为评论放入,但值得重复: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
;
希望对您有所帮助。