先前排名为零时如何分配排名(第 2 部分)
Posted
技术标签:
【中文标题】先前排名为零时如何分配排名(第 2 部分)【英文标题】:How to distribute ranks when prior rank is zero (part 2) 【发布时间】:2020-09-10 18:36:14 【问题描述】:这是对我之前的问题How to distribute values when prior rank is zero 的扩展。该解决方案适用于 postgres 环境,但现在我需要复制到 databricks 环境 (spark sql)。
问题和以前一样,但现在尝试确定如何将这个postgres查询转换为spark sql。基本上,如果数据中有差距(即按位置和 geo3 分组时没有 micro_geo),它会汇总分配量。对于所有位置和 zip3 组,“估算分配”将等于 1。
这是 postgres 查询,效果很好:
select location_code, geo3, distance_group, has_micro_geo, imputed_allocation from
(
select ia.*,
(case when has_micro_geo > 0
then sum(allocation) over (partition by location_code, geo3, grp)
else 0
end) as imputed_allocation
from (select s.*,
count(*) filter (where has_micro_geo <> 0) over (partition by location_code, geo3 order by distance_group desc) as grp
from staging_groups s
) ia
)z
但它不能很好地翻译并在数据块中产生此错误:
Error in SQL statement: ParseException:
mismatched input 'from' expecting <EOF>(line 1, pos 78)
== SQL ==
select location_code, geo3, distance_group, has_micro_geo, imputed_allocation from
------------------------------------------------------------------------------^^^
(
select ia.*,
(case when has_micro_geo > 0
then sum(allocation) over (partition by location_code, geo3, grp)
else 0
end) as imputed_allocation
from (select s.*,
count(*) filter (where has_micro_geo <> 0) over (partition by location_code, geo3 order by distance_group desc) as grp
from staging_groups s
) ia
)z
或者至少,如何转换这个创建“grp”的内部查询的一部分,然后其余的可能会起作用。我一直在尝试用其他东西替换这个过滤器逻辑,但尝试并没有达到预期的效果。
select s.*,
count(*) filter (where has_micro_geo <> 0) over (partition by location_code, geo3 order by distance_group desc) as grp
from staging_groups s
这是一个带有数据 https://www.db-fiddle.com/f/wisvDZJL9BkWxNFkfLXdEu/0 的 db-fiddle,当前设置为 postgres,但我需要再次在 spark sql 环境中运行它。我已尝试将其分解并创建不同的表格,但我的小组无法按预期工作。
这是一个更好地可视化输出的图像:
【问题讨论】:
【参考方案1】:你需要重写这个子查询:
select s.*,
count(*) filter (where has_micro_geo <> 0) over (partition by location_code, geo3 order by distance_group desc) as grp
from staging_groups s
虽然窗口和聚合函数的filter()
子句是标准SQL,但目前很少有数据库支持它。相反,考虑一个条件窗口sum()
,它会产生相同的结果:
select s.*,
sum(case when has_micro_geo <> 0 then 1 else 0 end) over (partition by location_code, geo3 order by distance_group desc) as grp
from staging_groups s
我认为查询的其余部分应该在 Spark SQL 中运行良好。
【讨论】:
【参考方案2】:由于has_micro_geo
已经是 0/1 标志,您可以将计数(过滤器)重写为
sum(has_micro_geo)
over (partition by location_code, geo3
order by distance_group desc
rows unbounded preceding) as grp
添加rows unbounded preceding
以避免默认的range unbounded preceding
可能会降低性能。
顺便说一句,我已经在我对 Gordon 对您先前问题的解决方案的评论中写道:-)
【讨论】:
以上是关于先前排名为零时如何分配排名(第 2 部分)的主要内容,如果未能解决你的问题,请参考以下文章