Snowflake cloud data platform 雪花将属性值透视到对象数组中的列中
编辑:我给出了错误的示例数据。更新了一些详细信息,并将虚拟数据转换为经过消毒的实际数据 源系统:Freshdesk via Stitch 表结构:Snowflake cloud data platform 雪花将属性值透视到对象数组中的列中,snowflake-cloud-data-platform,Snowflake Cloud Data Platform,编辑:我给出了错误的示例数据。更新了一些详细信息,并将虚拟数据转换为经过消毒的实际数据 源系统:Freshdesk via Stitch 表结构: create or replace TABLE TICKETS ( CC_EMAILS VARIANT, COMPANY VARIANT, COMPANY_ID NUMBER(38,0), CREATED_AT TIMESTAMP_TZ(9), CUSTOM_FIELDS VARIANT, DUE_BY
create or replace TABLE TICKETS (
CC_EMAILS VARIANT,
COMPANY VARIANT,
COMPANY_ID NUMBER(38,0),
CREATED_AT TIMESTAMP_TZ(9),
CUSTOM_FIELDS VARIANT,
DUE_BY TIMESTAMP_TZ(9),
FR_DUE_BY TIMESTAMP_TZ(9),
FR_ESCALATED BOOLEAN,
FWD_EMAILS VARIANT,
ID NUMBER(38,0) NOT NULL,
IS_ESCALATED BOOLEAN,
PRIORITY FLOAT,
REPLY_CC_EMAILS VARIANT,
REQUESTER VARIANT,
REQUESTER_ID NUMBER(38,0),
RESPONDER_ID NUMBER(38,0),
SOURCE FLOAT,
SPAM BOOLEAN,
STATS VARIANT,
STATUS FLOAT,
SUBJECT VARCHAR(16777216),
TAGS VARIANT,
TICKET_CC_EMAILS VARIANT,
TYPE VARCHAR(16777216),
UPDATED_AT TIMESTAMP_TZ(9),
_SDC_BATCHED_AT TIMESTAMP_TZ(9),
_SDC_EXTRACTED_AT TIMESTAMP_TZ(9),
_SDC_RECEIVED_AT TIMESTAMP_TZ(9),
_SDC_SEQUENCE NUMBER(38,0),
_SDC_TABLE_VERSION NUMBER(38,0),
EMAIL_CONFIG_ID NUMBER(38,0),
TO_EMAILS VARIANT,
PRODUCT_ID NUMBER(38,0),
GROUP_ID NUMBER(38,0),
ASSOCIATION_TYPE NUMBER(38,0),
ASSOCIATED_TICKETS_COUNT NUMBER(38,0),
DELETED BOOLEAN,
primary key (ID)
);
注意变量字段、自定义字段。它在api和snowflake之间经历了一次不幸的转换。结果字段包含3个或更多对象的数组,每个对象都是自定义字段。我无法更改数据格式。示例:
# values could be null
[
{
"name": "cf_request",
"value": "none"
},
{
"name": "cf_related_with",
"value": "none"
},
{
"name": "cf_question",
"value": "none"
}
]
# or values could have a combination of null and non-null values
[
{
"name": "cf_request",
"value": "none"
},
{
"name": "cf_related_with",
"value": "none"
},
{
"name": "cf_question",
"value": "concern"
}
]
# or they could all have non-null values
[
{
"name": "cf_request",
"value": "issue with timer"
},
{
"name": "cf_related_with",
"value": "timer stopped"
},
{
"name": "cf_question",
"value": "technical problem"
}
]
我基本上希望将这些字段集中到select查询中,其中name属性的值成为列标题。使输出类似于以下内容:
+----+------------------+-----------------+-------------------+-----------------------------+
| id | cf_request | cf_related_with | cf_question | all_other_fields |
+----+------------------+-----------------+-------------------+-----------------------------+
| 5 | issue with timer | timer stopped | technical problem | more data about this ticket |
| 6 | hq | laptop issues | some value | more data |
| 7 | a thing | about a thing | about something | more data |
+----+------------------+-----------------+-------------------+-----------------------------+
是否有一个函数可以搜索数组对象的值并返回具有限定值的对象?比如:
select
id,
get_object_where(name = 'category', value) as category,
get_object_where(name = 'subcategory', value) as category,
get_object_where(name = 'subsubcategory', value) as category
from my_data_table
不幸的是,PIVOT需要一个聚合函数,我尝试使用min和max,但只返回null值。如果有另一种不需要聚合的语法,那么与此方法类似的东西将非常有用
with arr as (
select
id,
cs.value:name col_name,
cs.value:value col_value
from my_data_table,
lateral flatten(input => custom_fields) cs
)
select
*
from arr
pivot(col_name for col_value in ('category', 'subcategory', 'subsubcategory')
as p (id, category, subcategory, subsubcategory);
可以使用以下方法,但它存在缺陷,因为每当添加新的自定义字段时,我都必须添加案例来说明阵列中的新位置
select
id,
case
when custom_fields[0]:name = 'cf_request' then custom_fields[0]:value
when custom_fields[1]:name = 'cf_request' then custom_fields[1]:value
when custom_fields[2]:name = 'cf_request' then custom_fields[2]:value
when custom_fields[2]:name = 'cf_request' then custom_fields[3]:value
else null
end cf_request,
case
when custom_fields[0]:name = 'cf_related_with' then custom_fields[0]:value
when custom_fields[1]:name = 'cf_related_with' then custom_fields[1]:value
when custom_fields[2]:name = 'cf_related_with' then custom_fields[2]:value
when custom_fields[2]:name = 'cf_related_with' then custom_fields[3]:value
else null
end cf_related_with,
case
when custom_fields[0]:name = 'cf_question' then custom_fields[0]:value
when custom_fields[1]:name = 'cf_question' then custom_fields[1]:value
when custom_fields[2]:name = 'cf_question' then custom_fields[2]:value
when custom_fields[2]:name = 'cf_question' then custom_fields[3]:value
else null
end cf_question,
created_at
from my_db.my_schema.tickets;
我想你差点就成功了。您只需要在col_名称周围添加一个max或min。正如您所说的,它需要一个聚合函数,像max或min这样的函数在这里可以工作,因为它是在您拥有的名称/值对上聚合的。例如,如果您有2个子类别值,它将选择最小/最大值。从您的示例来看,这似乎不是问题,因此它将始终选择您想要的值。我可以通过以下查询复制您的场景:
WITH x AS (
SELECT parse_json('[{"name": "category","value": "Bikes"},{"name": "subcategory","value": "Mountain Bikes"},{"name": "subsubcategory","value": "hardtail bikes"}]')::VARIANT as field_var
),
arr as (
select
seq,
cs.value:name::varchar col_name,
cs.value:value::varchar col_value
from x,
lateral flatten(input => x.field_var) cs
)
select
*
from arr
pivot(max(col_value) for col_name in ('category','subcategory','subsubcategory')) as p (seq, category, subcategory, subsubcategory);
我想你差点就成功了。您只需要在col_名称周围添加一个max或min。正如您所说的,它需要一个聚合函数,像max或min这样的函数在这里可以工作,因为它是在您拥有的名称/值对上聚合的。例如,如果您有2个子类别值,它将选择最小/最大值。从您的示例来看,这似乎不是问题,因此它将始终选择您想要的值。我可以通过以下查询复制您的场景:
WITH x AS (
SELECT parse_json('[{"name": "category","value": "Bikes"},{"name": "subcategory","value": "Mountain Bikes"},{"name": "subsubcategory","value": "hardtail bikes"}]')::VARIANT as field_var
),
arr as (
select
seq,
cs.value:name::varchar col_name,
cs.value:value::varchar col_value
from x,
lateral flatten(input => x.field_var) cs
)
select
*
from arr
pivot(max(col_value) for col_name in ('category','subcategory','subsubcategory')) as p (seq, category, subcategory, subsubcategory);
我已经回答了下面的问题,但我确实想说,很遗憾,您的源数据不理解JSON名称/值对的概念。如果他们有,这将是一个直接的选择。不过,你似乎知道这一点-freshdesk API很好地代表了数据。我正在使用Stitch将数据复制到Snowflake中,我认为Stitch中的Freshdesk集成就是Singer.io tap Freshdesk将数据转换成这种格式。我编写了一个Snowflake存储过程来获取Snowflake中的动力学轴,检查我在下面的回答,但是我想评论一下,很遗憾您的源数据不理解JSON名称/值对的概念。如果他们有,这将是一个直接的选择。不过,你似乎知道这一点-freshdesk API很好地代表了数据。我正在使用Stitch将数据复制到Snowflake中,我认为Stitch中的Freshdesk集成就是Singer.io tap Freshdesk将数据转换为这种格式。我编写了一个Snowflake存储过程以获取Snowflake中的动力学轴,请检查,感谢您花时间回答此问题。我想通过创建一个示例来消除不必要的细节。我脱得太多了。我正在用实际数据和模式进行更新。对于给您带来的不便,我真的很抱歉。所以,您基本上需要一种动态的方式来完成我静态展示的内容。我认为您可以使用Javascript存储过程来实现这一点,在该存储过程中,您可以在JSON字段中获取所有可能的值,然后动态生成上面提到的SQL。我以前在Python中也做过类似的事情,但JS不是我的强项。非常确定这是可能的。我无法使用pivot使用min或max返回准确的结果。我将再次查看。我确信我可以找到动态生成查询的JS。只要我能得到pivot以返回正确的结果,我就会接受答案。@Stephenloyd您是否有在同一记录的同一列名称上有多个列值的情况?如果不是,则最小/最大值应起作用。如果您需要帮助,请随时发布您看到的内容。我在轴上翻转了col_值和col_名称。结果我得到了所有的空值。感谢您的帮助。感谢您抽出时间回答此问题。我想通过创建一个示例来消除不必要的细节。我脱得太多了。我正在用实际数据和模式进行更新。对于给您带来的不便,我真的很抱歉。所以,您基本上需要一种动态的方式来完成我静态展示的内容。我认为您可以使用Javascript存储过程来实现这一点,在该存储过程中,您可以在JSON字段中获取所有可能的值,然后动态生成上面提到的SQL。我以前在Python中也做过类似的事情,但JS不是
这不是我的强项。非常确定这是可能的。我无法使用pivot使用min或max返回准确的结果。我将再次查看。我确信我可以找到动态生成查询的JS。只要我能得到pivot以返回正确的结果,我就会接受答案。@Stephenloyd您是否有在同一记录的同一列名称上有多个列值的情况?如果不是,则最小/最大值应起作用。如果您需要帮助,请随时发布您看到的内容。我在轴上翻转了col_值和col_名称。结果我得到了所有的空值。谢谢你的帮助。