我有一个查询按两个变量分组以获得另一个变量。为了维护我的表结构以供以后的计算,我将listagg()另外两个变量保存到查询的下一个阶段。但是,当我尝试在listagg()列之后进行两次展平时,我的数据会重复多次。
示例:my_table
Post
结果:
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
答案 0 :(得分:4)
正如您自己注意到的那样,您需要4条记录。有两种方法可以实现,它们都利用index
生成的flatten
列,它代表输入中生成的值的位置(请参阅Flatten Documentation)
第一种方法是获取查询结果,并添加这些索引列,这是一个例子:
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对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
答案 1 :(得分:0)
要从具有相同索引的多个数组中获取元素,我们可以使用数组访问器:
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;