You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Snowflake中将多列同键Object解析为行格式

Snowflake中Object类型列的长格式与宽格式转换方案

一、转换为长格式(行转列)

针对需求,只需FLATTEN其中一个Object列获取时间周期的KEY,再通过KEY直接提取其他Object列对应的值即可,这种方式无需多次JOIN,性能更优且支持扩展任意数量的Object列。

示例代码

WITH smpl AS (
SELECT
  '12a' AS customer_id,
  OBJECT_CONSTRUCT(
    'd1910', 0,
    'd1911', 26,
    'd1912', 6,
    'd2001', 73) as activity_count,
   OBJECT_CONSTRUCT(
    'd1910', 0,
    'd1911', 260.1,
    'd1912', 30,
    'd2001', 712.3) AS activity_duration
UNION ALL
SELECT
  '13b' AS customer_id,
  OBJECT_CONSTRUCT(
    'd1910', 1,
    'd1911', 2,
    'd1912', 3,
    'd2001', 4) as activity_count,
   OBJECT_CONSTRUCT(
    'd1910', 1,
    'd1911', 2.2,
    'd1912', 3.3,
    'd2001', 4.3) AS activity_duration
)
SELECT
  s.customer_id,
  f.key AS time_period,
  -- 通过KEY提取对应Object列的值
  s.activity_count[f.key]::INT AS activity_count,
  s.activity_duration[f.key]::NUMERIC AS activity_duration
FROM smpl s
-- 仅FLATTEN一个Object列获取所有时间周期
LATERAL FLATTEN(input => s.activity_count) f;

说明

  • 只需FLATTEN任意一个包含完整时间周期的Object列(比如activity_count),就能得到所有time_period值
  • 其他Object列通过列名[KEY]的方式直接取值,新增列时只需复制这一行格式修改列名即可,完美支持50+列扩展

二、转换为宽格式(列转行,类似BigQuery的.*展开)

Snowflake中可以通过FLATTEN + PIVOT实现动态将Object的KEY转为列名,也可以直接用列名:KEY的方式手动指定列(适合已知KEY的场景)。

方式1:动态PIVOT(自动识别所有KEY)

WITH smpl AS (
SELECT
  '12a' AS customer_id,
  OBJECT_CONSTRUCT(
    'd1910', 0,
    'd1911', 26,
    'd1912', 6,
    'd2001', 73) as activity_count,
   OBJECT_CONSTRUCT(
    'd1910', 0,
    'd1911', 260.1,
    'd1912', 30,
    'd2001', 712.3) AS activity_duration
UNION ALL
SELECT
  '13b' AS customer_id,
  OBJECT_CONSTRUCT(
    'd1910', 1,
    'd1911', 2,
    'd1912', 3,
    'd2001', 4) as activity_count,
   OBJECT_CONSTRUCT(
    'd1910', 1,
    'd1911', 2.2,
    'd1912', 3.3,
    'd2001', 4.3) AS activity_duration
),
-- 先将activity_count展开为长格式
count_flat AS (
  SELECT customer_id, key, value::INT AS count_val
  FROM smpl, LATERAL FLATTEN(input => activity_count)
),
-- 再将activity_duration展开为长格式
duration_flat AS (
  SELECT customer_id, key, value::NUMERIC AS duration_val
  FROM smpl, LATERAL FLATTEN(input => activity_duration)
)
-- 分别PIVOT两个指标
SELECT
  p1.customer_id,
  -- 重命名列,加上指标前缀
  p1.d1910 AS activity_count_d1910,
  p1.d1911 AS activity_count_d1911,
  p1.d1912 AS activity_count_d1912,
  p1.d2001 AS activity_count_d2001,
  p2.d1910 AS activity_duration_d1910,
  p2.d1911 AS activity_duration_d1911,
  p2.d1912 AS activity_duration_d1912,
  p2.d2001 AS activity_duration_d2001
FROM (
  SELECT * FROM count_flat PIVOT(MAX(count_val) FOR key IN ('d1910','d1911','d1912','d2001'))
) p1
JOIN (
  SELECT * FROM duration_flat PIVOT(MAX(duration_val) FOR key IN ('d1910','d1911','d1912','d2001'))
) p2 ON p1.customer_id = p2.customer_id;

方式2:手动指定列(适合已知KEY的场景)

如果已经明确Object中的KEY,可以直接用列名:KEY提取,写法更简洁:

WITH smpl AS (
SELECT
  '12a' AS customer_id,
  OBJECT_CONSTRUCT(
    'd1910', 0,
    'd1911', 26,
    'd1912', 6,
    'd2001', 73) as activity_count,
   OBJECT_CONSTRUCT(
    'd1910', 0,
    'd1911', 260.1,
    'd1912', 30,
    'd2001', 712.3) AS activity_duration
UNION ALL
SELECT
  '13b' AS customer_id,
  OBJECT_CONSTRUCT(
    'd1910', 1,
    'd1911', 2,
    'd1912', 3,
    'd2001', 4) as activity_count,
   OBJECT_CONSTRUCT(
    'd1910', 1,
    'd1911', 2.2,
    'd1912', 3.3,
    'd2001', 4.3) AS activity_duration
)
SELECT
  customer_id,
  activity_count:d1910::INT AS activity_count_d1910,
  activity_count:d1911::INT AS activity_count_d1911,
  activity_count:d1912::INT AS activity_count_d1912,
  activity_count:d2001::INT AS activity_count_d2001,
  activity_duration:d1910::NUMERIC AS activity_duration_d1910,
  activity_duration:d1911::NUMERIC AS activity_duration_d1911,
  activity_duration:d1912::NUMERIC AS activity_duration_d1912,
  activity_duration:d2001::NUMERIC AS activity_duration_d2001
FROM smpl;

内容的提问来源于stack exchange,提问作者internet_geek

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 21:30:45