7

2 つの変数でグループ化して別の合計を取得するクエリがあります。後の計算のためにテーブル構造を維持するために、クエリの次の段階のために保存する他の 2 つの変数を listagg() します。ただし、後で listagg() 列を 2 つフラット化しようとすると、データが何度も繰り返されます。

例: 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
4

2 に答える 2

16

気づいたように、4 つのレコードが必要です。それには 2 つの方法があります。どちらも によって生成されたindex列を利用しますflatten。これは、入力内の生成された値の位置を表します ( 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 つのフラット化 + インデックスによるルックアップの使用

より簡単で、より効率的で、より柔軟な方法 (そのような複数の配列がある場合、または配列インデックスが 1 対 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

于 2016-04-22T23:07:33.233 に答える