【问题标题】:Lateral flatten two columns without repetition in snowflake横向压平两列,雪花中不重复
【发布时间】:2016-08-16 08:44:14
【问题描述】:

我有一个查询,它按两个变量分组以获得另一个变量的总数。为了为以后的计算维护我的表结构,我列出了另外两个变量以保存以用于下一阶段的查询。但是,当我尝试对 listagg() 列进行两次展平时,我的数据会重复很多次。

示例:my_table

   id   |     list1       | code|   list2  | total
--------|-----------------|-----|----------|---
2434166 | 735,768,769,746 | 124 | 21,2,1,6 | 30


select
id,
list1_table.value::int as list1_val,
code,
list2.value::int as list2_val,
total

from my_table
lateral flatten(input=>split(list1, ',')) list1_table,
lateral flatten(input=>split(list2, ',')) list2_table

结果:

   id   |     list1       | code|   list2  | total
--------|-----------------|-----|----------|---
2434166 |      768        | 124 |     2    | 30
2434166 |      735        | 124 |     2    | 30
2434166 |      746        | 124 |     2    | 30
2434166 |      769        | 124 |     2    | 30
2434166 |      768        | 124 |     21   | 30
2434166 |      735        | 124 |     21   | 30
2434166 |      746        | 124 |     21   | 30
2434166 |      769        | 124 |     21   | 30
2434166 |      768        | 124 |     6    | 30
2434166 |      735        | 124 |     6    | 30
2434166 |      746        | 124 |     6    | 30
2434166 |      769        | 124 |     6    | 30
2434166 |      768        | 124 |     1    | 30
2434166 |      735        | 124 |     1    | 30
2434166 |      746        | 124 |     1    | 30
2434166 |      769        | 124 |     1    | 30

我了解发生了什么,但我只是想知道如何获得我想要的结果:

   id   |     list1       | code|   list2  | total
--------|-----------------|-----|----------|---
2434166 |      768        | 124 |     2    | 30
2434166 |      735        | 124 |     21   | 30
2434166 |      746        | 124 |     6    | 30
2434166 |      769        | 124 |     1    | 30

【问题讨论】:

    标签: snowflake-cloud-data-platform


    【解决方案1】:

    要从具有相同索引的多个数组中获取元素,我们可以使用数组访问器:

    SELECT t.id, t.code, t.total, s.ind,
         STRTOK_TO_ARRAY(t.list1, ',')[s.ind]::int AS list1_val,
         STRTOK_TO_ARRAY(t.list2, ',')[s.ind]::int AS list2_val
    FROM t
    ,(SELECT ROW_NUMBER() OVER(ORDER BY seq4()) - 1 AS ind 
      FROM TABLE(GENERATOR(ROWCOUNT => 10))) s  -- here up to 10 elements
    WHERE list1_val IS NOT NULL
    ORDER BY t.id, s.ind;
    

    这个想法是生成计数,然后访问元素。

    样本数据:

    CREATE OR REPLACE TABLE t(id INT, list1 TEXT, code INT, list2 TEXT, total INT) AS
    SELECT 6, '735,768,769,746', 124, '21,2,1,6', 30 UNION
    SELECT 7, '1,2,3'          , 1,   '10,20,30', 50;
    

    【讨论】:

      【解决方案2】:

      正如您自己注意到的,您需要 4 条记录。有两种方法可以做到这一点,都利用flatten产生的index列,它表示产生的值在输入中的位置(见Flatten Documentation

      使用 2 个展平和索引选择

      第一种方法是获取查询结果,并添加这些索引列,这是一个示例:

      select id,
      list1_table.value::int as list1_val, list1_table.index as list1_index, code,
      list2_table.value::int as list2_val, list2_table.index as list2_index, total
      from my_table,
      lateral flatten(input=>split(list1, ',')) list1_table,
      lateral flatten(input=>split(list2, ',')) list2_table;
      ---------+-----------+-------------+------+-----------+-------------+-------+
         ID    | LIST1_VAL | LIST1_INDEX | CODE | LIST2_VAL | LIST2_INDEX | TOTAL |
      ---------+-----------+-------------+------+-----------+-------------+-------+
       2434166 | 735       | 0           | 124  | 21        | 0           | 30    |
       2434166 | 735       | 0           | 124  | 2         | 1           | 30    |
       2434166 | 735       | 0           | 124  | 1         | 2           | 30    |
       2434166 | 735       | 0           | 124  | 6         | 3           | 30    |
       2434166 | 768       | 1           | 124  | 21        | 0           | 30    |
       2434166 | 768       | 1           | 124  | 2         | 1           | 30    |
       2434166 | 768       | 1           | 124  | 1         | 2           | 30    |
       2434166 | 768       | 1           | 124  | 6         | 3           | 30    |
       2434166 | 769       | 2           | 124  | 21        | 0           | 30    |
       2434166 | 769       | 2           | 124  | 2         | 1           | 30    |
       2434166 | 769       | 2           | 124  | 1         | 2           | 30    |
       2434166 | 769       | 2           | 124  | 6         | 3           | 30    |
       2434166 | 746       | 3           | 124  | 21        | 0           | 30    |
       2434166 | 746       | 3           | 124  | 2         | 1           | 30    |
       2434166 | 746       | 3           | 124  | 1         | 2           | 30    |
       2434166 | 746       | 3           | 124  | 6         | 3           | 30    |
      ---------+-----------+-------------+------+-----------+-------------+-------+
      

      如您所见,您感兴趣的行是具有相同索引的行。

      所以要在横向连接发生后通过选择这些行来获得结果:

      select id,
      list1_table.value::int as list1_val, code,
      list2_table.value::int as list2_val, total
      from my_table,
      lateral flatten(input=>split(list1, ',')) list1_table,
      lateral flatten(input=>split(list2, ',')) list2_table 
      where list1_table.index = list2_table.index;
      ---------+-----------+------+-----------+-------+
         ID    | LIST1_VAL | CODE | LIST2_VAL | TOTAL |
      ---------+-----------+------+-----------+-------+
       2434166 | 735       | 124  | 21        | 30    |
       2434166 | 768       | 124  | 2         | 30    |
       2434166 | 769       | 124  | 1         | 30    |
       2434166 | 746       | 124  | 6         | 30    |
      ---------+-----------+------+-----------+-------+
      

      使用 1 展平 + 按索引查找

      一种更简单、更高效、更灵活的方法(如果您有多个类似的数组,或者数组索引相关但不是一对一的情况下很有用)是仅在一个数组上展平,然后使用生成的元素用于在其他数组中查找值。

      这是一个例子:

      select id, list1_table.value::int as list1_val, code, 
      split(list2,',')[list1_table.index]::int as list2_val,  -- array lookup here 
      total
      from my_table, lateral flatten(input=>split(list1, ',')) list1_table;
      ---------+-----------+------+-----------+-------+
         ID    | LIST1_VAL | CODE | LIST2_VAL | TOTAL |
      ---------+-----------+------+-----------+-------+
       2434166 | 735       | 124  | 21        | 30    |
       2434166 | 768       | 124  | 2         | 30    |
       2434166 | 769       | 124  | 1         | 30    |
       2434166 | 746       | 124  | 6         | 30    |
      ---------+-----------+------+-----------+-------+
      

      看看我们如何简单地使用扁平化list1时产生的索引来查找list2中的值

      【讨论】:

      • 谢谢,太好了!
      • 哇,按索引查找非常出色且可扩展!比雪花文档更有帮助,谢谢!
      猜你喜欢
      • 2021-08-16
      • 2020-03-24
      • 2020-06-17
      • 1970-01-01
      • 2020-02-09
      • 2022-08-20
      • 2021-04-25
      • 2020-12-03
      • 2019-08-10
      相关资源
      最近更新 更多