在Java中尝试解密时出现 "算法错误 "的错误[英] Use something like TOP with GROUP BY

本文是小编为大家收集整理的关于在Java中尝试解密时出现 "算法错误 "的错误的处理方法,想解了在Java中尝试解密时出现 "算法错误 "的错误的问题怎么解决?在Java中尝试解密时出现 "算法错误 "的错误问题的解决办法?那么可以参考本文帮助大家快速定位并解决问题。

问题描述

表table1如下

+--------+-------+-------+------------+-------+
| flight |  orig |  dest |  passenger |  bags |
+--------+-------+-------+------------+-------+
|   1111 |  sfo  |  chi  |  david     |     3 |
|   1112 |  sfo  |  dal  |  david     |     7 |
|   1112 |  sfo  |  dal  |  kim       |     10|
|   1113 |  lax  |  san  |  ameera    |     5 |
|   1114 |  lax  |  lfr  |  tim       |     6 |
|   1114 |  lax  |  lfr  |  jake      |     8 |
+--------+-------+-------+------------+-------+

我正在通过 orig 聚合表格,如下所示

select 
  orig
  , count(*) flight_cnt
  , count(distinct passenger) as pass_cnt
  , percentile_cont(0.5) within group ( order by bags ASC) as bag_cnt_med
from table1
group by orig

我需要为每个 orig 组添加具有最长名称 ( length(passenger) ) 的 passenger - 我该怎么做?

预期输出

+------+-------------+-----------+---------------+-------------------+
| orig |  flight_cnt |  pass_cnt |  bags_cnt_med | pass_max_len_name |
+------+-------------+-----------+---------------+-------------------+
| sfo  |           3 |         2 |             7 |  david            |
| lax  |           3 |         3 |             6 | ameera            |
+------+-------------+-----------+---------------+-------------------+

推荐答案

您可以使用DISTINCT ON方便地检索每组姓名最长的乘客.

但我认为没有办法在一个 SELECT 中将它(或任何其他简单的方法)与您的原始查询结合起来.我建议加入两个单独的子查询:

SELECT *
FROM  (  -- your original query
   SELECT orig
        , count(*) AS flight_cnt
        , count(distinct passenger) AS pass_cnt
        , percentile_cont(0.5) WITHIN GROUP (ORDER BY bags) AS bag_cnt_med
   FROM   table1
   GROUP  BY orig
   ) org_query
JOIN  (  -- my addition
   SELECT DISTINCT ON (orig) orig, passenger AS pass_max_len_name
   FROM   table1
   ORDER  BY orig, length(passenger) DESC NULLS LAST
   ) pas USING (orig);
join 子句中的

USING 方便地只输出orig 的一个实例,因此您可以在外部SELECT 中简单地使用SELECT *.

如果passenger可以为NULL,则添加NULLS LAST很重要:

从同一组中具有相同最大长度的多个乘客姓名中,您将获得任意选择 - 除非您向 ORDER BY 添加更多表达式作为决胜局.上面链接的答案中有详细说明.

性能?

通常,单次扫描更胜一筹,尤其是顺序扫描.

上述查询使用两次扫描(可能是索引/仅索引扫描).但是第二次扫描相对便宜,除非表太大而无法放入缓存(大多数情况下).Lukas 建议了一个替代查询,其中只添加了一个单个 SELECT:

, (ARRAY_AGG (passenger ORDER BY LENGTH (passenger) DESC))[1]  -- I'd add NULLS LAST

这个想法很聪明,但是上次我测试,array_agg 和 ORDER BY 并没有这样好.(每组 ORDER BY 的开销很大,而且数组处理也很昂贵.)

使用自定义聚合函数可以更便宜地使用相同的方法 first() 就像 Postgres Wiki 中的指示.或者,使用 一个用 C 编写的版本,可在 PGXN 上使用,速度更快.消除了数组处理的额外成本,但我们仍然需要每个组的 ORDER BY.可能更快仅适用于少数群体.然后你会添加:

 , first(passenger ORDER BY length(passenger) DESC NULLS LAST)

戈登卢卡斯 还要提到窗口函数 first_value().窗口函数在聚合函数之后应用.要在同一个 SELECT 中使用它,我们需要先聚合 passenger - 捕获 22.Gordon 使用子查询解决了这个问题 - 另一个使用标准 Postgres 具有良好性能的候选者.

first() 在没有子查询的情况下做同样的事情,应该更简单,更快一点.但是对于大多数每组行数很少的情况,它仍然不会比单独的 DISTINCT ON 快.对于每组很多行,递归 CTE 技术通常更快.如果您有一个单独的表保存所有相关的唯一 orig 值,还有更快的技术.详情:

  • 优化 GROUP BY 查询以检索每个用户的最新记录

最佳解决方案取决于各种因素.布丁的证明是在吃.要优化性能,您必须使用您的设置进行测试.上面的查询应该是最快的了.

其他推荐答案

一种方法是使用窗口函数first_value().不幸的是,这不能作为聚合函数使用:

select orig,
       count(*) flight_cnt,
       count(distinct passenger) as pass_cnt,
       percentile_cont(0.5) within group ( order by bags ASC) as bag_cnt_med,
       max(longest_name) as longest_name
from (select t1.*,
             first_value(name) over (partition by orig order by length(name) desc) as longest_name
      from table1
     ) t1
group by orig;

其他推荐答案

您正在寻找类似于 Oracle 的 KEEP FIRST/LAST 的东西,您可以根据聚合(姓名长度)获得值(乘客姓名).据我所知,PostgreSQL 没有这样的功能.

解决这个问题的一种方法是一个技巧:结合长度和名称,得到最大值,然后提取名称:'0005david' > '0003kim' 等

select 
  orig
  , count(*) flight_cnt
  , count(distinct passenger) as pass_cnt
  , percentile_cont(0.5) within group ( order by bags ASC) as bag_cnt_med,
  , substr(max(to_char(char_length(passenger), '0000') || passenger), 5) as name
from table1
group by orig
order by orig;

本文地址:https://www.itbaoku.cn/post/1763749.html