如何在 AWS Redshift 数据库中获取过滤器和分组依据子句的子字符串
Posted
技术标签:
【中文标题】如何在 AWS Redshift 数据库中获取过滤器和分组依据子句的子字符串【英文标题】:How to get substring for filter and group by clause in AWS Redshift database 【发布时间】:2018-04-24 06:37:30 【问题描述】:如何从包含 AWS Redshift 数据库中过滤器和分组依据子句记录的列中获取子字符串。
我有如下记录的表格:
Table_Id | Categories | Value
<ID> | ABC1; ABC1-1; XYZ | 10
<ID> | ABC1; ABC1-2; XYZ | 15
<ID> | XYZ | 5
.....
现在我想根据“ABC1”或“ABC1 和 XYZ”等单个类别过滤记录
查询的预期输出如下:
Table_Id | Categories | Value
<ID> | ABC1 | 25
<ID> | ABC1-1 | 10
<ID> | ABC1-2 | 15
<ID> | XYZ | 30
.....
因此需要根据各个类别对结果进行分组。
【问题讨论】:
输出中的聚合函数是什么?如果是总和,则 ABC1 不能为 15,因为 ABC1 在两行中,即 10+15 是的@AlexYes,它的错字。我更新了预期结果。实际上我想要各个类别的值。 【参考方案1】:如果您在任何“类别”单元格中最多有 3 个值,您可以取消嵌套单元格,获取唯一值列表并在连接条件中使用该列表,如下所示:
WITH
values as (
select distinct category
from (
select distinct split_part(categories,';',1) as category from your_table
union select distinct split_part(categories,';',2) from your_table
union select distinct split_part(categories,';',3) from your_table
)
where nullif(category,'') is not null
)
SELECT
t2.category
,sum(t1.value)
FROM your_table t1
JOIN values t2
ON split_part(categories,';',1)=t2.category
OR split_part(categories,';',2)=t2.category
OR split_part(categories,';',3)=t2.category
如果您有超过 3 个选项,只需在 WITH
部分和连接条件中添加另一个 split_part
级别
【讨论】:
这是个好主意@Alexyes!我会更新我的答案,指出你的答案是最好的半动态选项。 谢谢@AlexYes。这似乎是一个很好的解决方案。我将更新您的解决方案以满足我的要求,因为我有未预定义大小的动态类别字符串(类别列表可能非常位于单独的行中)。完成查询后,我将更新我的答案。 @RaviPatel 你只需要知道尽可能多的选项并相应地更新,我想你可以接受这个答案【参考方案2】:@JonScott、@AlexYes 和其他遇到类似情况的朋友。
我发现了比@AlexYes 建议的更好的方法。
我所做的是,我对生成单个记录的类别列进行了扁平化。 我可以进一步处理。
查询:
select row_number() over(order by 1) as r1,
to_char(timestamptz 'epoch' + date_time * interval '1 second', 'yyyy-mm-dd') AS DAY,
split_part(categories, ';', numbers.n) as catg,
value
from <TABLE>
join numbers
on numbers.n <= regexp_count(category_string, ';') + 1 <OTHER_CONDITIONS>
说明:
这里有两个函数很有用:第一个是 split_part 函数,它接受一个字符串,将其拆分为 ';'分隔符,并返回从拆分字符串中指定的第一个、第二个、...、第 n 个值;其次,regexp_count,它告诉我们在字符串中找到特定模式的次数。
【讨论】:
看起来很棒!【参考方案3】:要完全动态地执行此操作,您需要将“类别”列中的值转置或转置到单独的行中。 不幸的是,使用 redshift 无法实现“完全动态”的解决方案(事先不知道不同的值)。
您的选择如下:
在另一个答案中使用 AlexYes 建议的方法。这是 半动态的,可能是您的最佳选择。
在 Redshift 之外,运行一些 ETL 代码来执行 列 -> 多行 ETL。
创建一个硬编码类型解决方案,并执行如下所示的枢轴:
select table_id,'ABC1' as category, case when concat(Categories,';') ilike '%ABC1;%' then value else 0 end as value from your_table 联合所有 select table_id,'ABC1-1' as category, case when concat(Categories,';')ilike '%ABC1-1;%' then value else 0 end as value from your_table 联合所有
等
【讨论】:
以上是关于如何在 AWS Redshift 数据库中获取过滤器和分组依据子句的子字符串的主要内容,如果未能解决你的问题,请参考以下文章
正则表达式:获取 AWS Redshift 中两个字符串之间的值
将数据从 Athena 或 Redshift 获取到 Sage maker 或 AWS Forecast 而不是平面文件