过滤数据透视表以仅包含具有数据的列 [Snowflake]

问题描述 投票:0回答:1

有点不寻常的要求。我们有一个可以提出调查问题的软件。任何调查都可以包含任意数量的问题(很容易从 1 到 30 个问题,但没有限制)。

用户的请求是为每个调查、response_ID 和问题提取一行数据。我已经完成了这一点,因此数据的格式为:

调查ID 响应_ID 问题1 问题2... 问题K Q1 Q2
ABC 1 1
ABC 2 4
防御 1 10
GHI 1 10
GHI 2 5

哪里 调查 ABC 有 2 个问题,评分范围为 1-10 调查 DEF 有 1 个问题,但问题不标准,因此显示在 Q1 列中 调查 GHI 有 2 个问题,评分范围为 1-10

如果我们在 BI 工具中选择调查 DEF,我们不想显示列 QUestion1-QuestionK,我们只想要列 Q1 和 Q2

我想到的方法是按 Survey_ID 和 Response_ID 进行分组,但我们不知道有多少列,因此我们无法聚合其余列

按调查 ID 进行过滤,然后仅对这些结果创建一个临时表,并排除 Survey_ID、Response_ID 和合并(*) 作为所有列,然后仅显示带有数据的列,但这似乎返回所有列,因为我认为我需要首先聚合,然后仅包含有数据的列

期望的输出:在BI工具中 按调查 ID 筛选:

DEF

调查 回应 Q1
防御 1 10

筛选调查 ID:

ABC

调查ID 回应 问题1 问题2
ABC 2 1 4

筛选:

GHI

调查ID 回应 问题1 问题2
GHI 2 10 5

任何有关聚合、删除空列等的帮助将不胜感激。

select survey_ID, Response_ID, max(\*)
from surveypivot
Where survey_ID = 'DEF'
group by Survey_ID,Response_ID
snowflake-cloud-data-platform pivot aggregate
1个回答
0
投票

免责声明:基于过滤器动态生成列列表是一个奇怪的请求,我个人不建议使用此类代码。

话虽如此,Snowflake SQL 的表达能力足以生成这样的输出:

WITH cte AS (
    SELECT *, OBJECT_CONSTRUCT(* EXCLUDE (SURVEY_ID, RESPONSE_ID)) AS obj
    FROM tab
    WHERE Survey_ID = 'GHI'
) ,cte_unpivot AS (
    SELECT SURVEY_ID, COUNT(*) OVER() AS RESPONSES, KEY, MAX(VALUE)::NUMBER AS VALUE
    FROM cte
    ,TABLE(FLATTEN(obj))
    GROUP BY SURVEY_ID, KEY
)
SELECT *
FROM cte_unpivot
PIVOT (MAX(VALUE) FOR KEY IN (ANY));

示例数据:

CREATE OR REPLACE TABLE tab(Survey_ID TEXT, Response_ID INT,Question1 INT,  Question2 INT, QuestionK INT,Q1 INT, Q2 INT)
AS    SELECT 'ABC',1 , 1,Null,Null, NULL,NULL
UNION SELECT 'ABC', 2,  Null,4,NULL,NULL,NULL
UNION SELECT 'DEF', 1,  Null ,Null, NULL,10 ,NULL
UNION SELECT 'GHI' ,1,  10, NULL, NULL, NULL, NULL
UNION SELECT 'GHI',NULL, 2, NULL, 5, NULL, NULL;

输出:

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.