给出下表,问题是从每个C1中查找例如前N个C2。
C1 C2
1 1
1 2
1 3
1 4
1 ...
2 1
2 2
2 3
2 4
2 ...
....
因此,如果N = 3,则结果为
C1 C2
1 1
1 2
1 3
2 1
2 2
2 3
....
建议的解决方案使用窗口功能并通过
进行分区例如,
SELECT rs.Field1,rs.Field2
FROM (
SELECT Field1,Field2, Rank()
over (Partition BY Section
ORDER BY RankCriteria DESC ) AS Rank
FROM table
) rs WHERE Rank <= 3
我想它的作用是排序,然后选择前N个。
但是,如果某些类别中的N个元素较少,则我们可以获得无排序的前N个,因为前N个必须包括该类别中的所有元素。
上面的查询使用Rank()。我的问题适用于其他窗口函数,例如row_num()或density_rank()。
有没有办法忽略案件的排序?
我也不知道底层引擎是否可以优化这种情况:排序之前内部分区/顺序是否考虑了外部where约束。
使用partition + order + where是从每个类别中获取前N个元素的方法。如果每个类别都具有N个以上的元素,则该方法非常理想,但否则会增加排序成本。我的问题是,是否有另一种方法在两种情况下都能正常工作。理想情况下,它会执行以下操作
for each category {
if # of element <= N:
continue
sort and get the top N
}
例如,但是有更好的SQL吗?
WITH table_with_count AS (
SELECT Field1, Field2, RankCriteria, count() over (PARTITION BY Section) as c
FROM table
),
rs AS (
SELECT Field1,Field2, Rank()
over (Partition BY Section
ORDER BY RankCriteria DESC ) AS Rank
FROM table_with_count
where c > 10
)
(SELECT Field1,Field2e FROM rs WHERE Rank <= 10)
union
(SELECT Field1,Field2 FROM table_with_count WHERE c <= 10)
答案 0 :(得分:1)
不,确实不应该存在。总体上,您在这里描述的是XY问题。
您似乎:
groupByKey
相同的行为模式。还有更有效的模式(MLPairRDDFunctions.topByKey
是最突出的示例),但是这些模式尚未移植到Dataset
API中,因此需要自定义Aggregator
选择(例如通过分位数逼近),但这会增加数据传递的次数,并且在许多情况下不会提供任何性能提升。
答案 1 :(得分:0)
这个评论太长了。
没有这样的优化。基本上,使用开窗子句对 all 数据进行排序。我想数据库引擎实际上可以为partition by
使用哈希算法,为order by
使用排序算法,但是我不认为这是常见的方法。
无论如何,该操作遍及整个集合,因此应为此进行优化。尝试不对子集进行排序会增加很多开销-例如,对每个子集多次运行排序并计算每个子集中的行数。
还要注意,在窗口函数之后,在逻辑上与“ 3”进行比较。我不认为窗口函数通常会针对此类后过滤进行优化(尽管再一次,这是可能的优化)。