在 Snowflake 中从表中取消嵌套

Posted

技术标签:

【中文标题】在 Snowflake 中从表中取消嵌套【英文标题】:Unnest from Table in Snowflake 【发布时间】:2021-09-28 09:11:11 【问题描述】:

我有下表:

PersonID    CW_MilesRun    PW_MilesRun    CM_MilesRun    PM_MilesRun
1           15             25             35             45         
2           10             20             30             40         
3           5              10             15             20         
...

我需要将此表拆分为一个垂直表,每个字段都有一个 id(即 CD_MilesRun =1、CW_MilesRun = 2 等),以便我的表看起来与此类似:

PersonID    TimeID    Description    C_MilesRun    P_MilesRun
1           1         Week           15            25
1           2         Month          35            45
2           1         Week           10            20
2           2         Month          30            40
3           1         Week           5             10
3           2         Month          15            20

在 postgres 中,我会使用类似于:

SELECT
    PersonID
  , unnest(array[1,2]) AS TimeID
  , unnest(array['Week','Month']) AS "Description"
  , unnest(array["CW_MilesRun","CM_MilesRun"]) C_MilesRun
  , unnest(array["PW_MilesRun","PM_MilesRun"]) P_MilesRun
FROM myTableHere
;

但是,我无法在雪花中使用类似的功能。有什么想法吗?

【问题讨论】:

【参考方案1】:

您可以使用FLATTEN()LATERAL 来获得您想要的结果,尽管查询完全不同。

with tbl as (select $1 PersonID, $2   CW_MilesRun, $3    PW_MilesRun, $4   CM_MilesRun, $5    PM_MilesRun from values (1, 15, 25, 35, 45),(2, 10, 20, 30, 40),(3, 5, 10, 15, 20))

select
    PersonID,
    t.value[0] TimeID,
    t.value[1] Description,
    iff(t.index=0,CW_MilesRun,CM_MilesRun) C_MilesRun,
    iff(t.index=1,PW_MilesRun,PM_MilesRun) P_MilesRun
from tbl, lateral flatten(parse_json('[[1, "Week"],[2, "Month"]]')) t;

PERSONID    TIMEID  DESCRIPTION C_MILESRUN  P_MILESRUN
1   1   "Week"  15  25
1   2   "Month" 35  45
2   1   "Week"  10  20
2   2   "Month" 30  40
3   1   "Week"  5   10
3   2   "Month" 15  20

附:使用t.* 来查看展平后可用的内容(也许这很明显。)

【讨论】:

谢谢!这似乎让我更接近我需要的地方。我的表实际上不止四列。我这里只是以这四个为例。是否有不需要内联 if 语句的选项。还是我必须嵌套我的 if 语句(总共 24 列)。 我想不出别的办法。也许会有更聪明的人出现;p @NatTaylor 找到了另一种方法......但不确定哪个更好......只是不同:-)【参考方案2】:

您也可以使用UNPIVOT 和NATURAL JOIN。

上面的答案很好......就像考虑其他做事方式一样......你永远不知道什么时候它可能适合你的需求 - 再加上让你接触到几个新的很酷的功能。

with cte as (
select
    1 PersonID,
    15 CW_MilesRun,
    25 PW_MilesRun,
    35 CM_MilesRun,
    45 PM_MilesRun
union
select
    2 PersonID,
    10 CW_MilesRun,
    20 PW_MilesRun,
    30 CM_MilesRun,
    40 PM_MilesRun
union
select
    3 PersonID,
    5 CW_MilesRun,
    10 PW_MilesRun,
    15 CM_MilesRun,
    20 PM_MilesRun
)
select * from
(select
   PersonID,
   CW_MilesRun weekly,
   CM_MilesRun monthly
 from
   cte
) unpivot (C_MilesRun for description in (weekly, monthly)) 
natural join 
(select * from
    (select
       PersonID,
       PW_MilesRun weekly,
       PM_MilesRun monthly
     from
       cte
    ) unpivot (P_MilesRun for description in (weekly, monthly))) f

【讨论】:

以上是关于在 Snowflake 中从表中取消嵌套的主要内容,如果未能解决你的问题,请参考以下文章

在 BigQuery 中取消嵌套多个嵌套字段

如何在迁移中从表中删除 softDeletes

在MySQL中从表中随机选择一行

在Oracle中从表中删除重复行

如何在 BigQuery 中取消嵌套多个数组?

如何在查询中取消嵌套嵌套表的集合?