Amazon Redshift/PostgreSQL中的高效分组
在分析处理中,通常需要将不重要的数据组折叠到结果表中的一行中。一种方法是通过CASE表达式进行分组,其中不重要的组通过CASE表达式合并成一行,返回单个值,例如,组为NULL。这个问题是关于在AmazonRedshift中执行此分组的有效方法,它基于ParAccel:close-Posgresql8.0的功能Amazon Redshift/PostgreSQL中的高效分组,sql,postgresql,group-by,amazon-redshift,paraccel,Sql,Postgresql,Group By,Amazon Redshift,Paraccel,在分析处理中,通常需要将不重要的数据组折叠到结果表中的一行中。一种方法是通过CASE表达式进行分组,其中不重要的组通过CASE表达式合并成一行,返回单个值,例如,组为NULL。这个问题是关于在AmazonRedshift中执行此分组的有效方法,它基于ParAccel:close-Posgresql8.0的功能 作为一个例子,考虑一个按类型和一个表中的URL的组,其中每行是单个URL访问。目标是执行聚合,以便为url访问计数超过某个阈值的每种类型、url对发出一行,并为访问计数低于该阈值的所有类型
作为一个例子,考虑一个按类型和一个表中的URL的组,其中每行是单个URL访问。目标是执行聚合,以便为url访问计数超过某个阈值的每种类型、url对发出一行,并为访问计数低于该阈值的所有类型、url对发出一个类型、NULL行。结果表中的其余列将具有基于此分组的总和/计数聚合
例如,以下数据+------+----------------------+-----------------------+
| type | url | < 50+ other columns > |
+------+----------------------+-----------------------+
| A | http://popular.com | |
| A | http://popular.com | |
| A | < 9997 more times> | |
| A | http://popular.com | |
| A | http://small-one.com | |
| B | http://tiny.com | |
| B | http://tiny-too.com | |
进一步的测试表明,双重聚合可以展开为涉及每个独立CASE表达式的所有独立查询的联合。在这种特殊情况下,对于大约有2亿行的样本数据集,这种方法的执行速度始终快30%。然而,该结果是特定于模式和数据的
with temp_counts as (SELECT type, url, COUNT(*) as cnt FROM t GROUP BY type, url)
select * from temp_counts WHERE cnt >= 10000
UNION ALL
SELECT type, NULL as url, SUM(cnt) as cnt from temp_counts
WHERE cnt < 10000
GROUP BY type
这表明了在Amazon Redshift中实现和优化任意分离分组和摘要的两种通用模式。如果性能对您很重要,请对两者进行基准测试
首先,根据类型url分组。
然后第二次分组类型,当访问次数<10000,则为NULL else url。
我使用了SQL Server语法,我希望它也适用于Postgres。您可以通过两个聚合来实现这一点:
select type, (case when cnt > XXX then url end) as url, sum(cnt) as visit_cnt
from (select type, url, count(*) as cnt
from t
group by type, url
) t
group by type, (case when cnt > XXX then url end)
order by type, sum(cnt) desc;
我在开始时也使用了此路径,但它生成了以下错误:执行SQL命令时发生错误:选择类型,当cnt>=10000时为case,然后url结束为url,sumcnt作为访问从选择类型开始,url。。。错误:t.cnt列必须出现在GROUP BY子句中,或用于聚合函数[SQL State=42803]我跟踪到了此特定功能的错误,在GROUP BY列中引用了亚马逊红移不支持的相关子查询的结果,并用信息更新了问题。@Sim。尝试使用组中的表达式的版本,因为我刚刚修改了它。嗯,如果我将嵌套的SELECT外部化为with子句,则上面的示例使用双重聚合,运行速度始终比两个SELECT的并集慢30%左右:一个是cnt>XXX,另一个是表单SELECT类型,url为NULL,来自temp_的SUMcnt计数,其中cnt
with temp_counts as (SELECT type, url, COUNT(*) as cnt FROM t GROUP BY type, url)
select * from temp_counts WHERE cnt >= 10000
UNION ALL
SELECT type, NULL as url, SUM(cnt) as cnt from temp_counts
WHERE cnt < 10000
GROUP BY type
select type, (case when cnt > XXX then url end) as url, sum(cnt) as visit_cnt
from (select type, url, count(*) as cnt
from t
group by type, url
) t
group by type, (case when cnt > XXX then url end)
order by type, sum(cnt) desc;