Postgres SQL - 前 2 条记录 GROUP BY 和 COUNT

Postgres SQL - Top 2 records GROUP BY and COUNT

我有一些数据格式如下:

Bus Route
Slowcoach SC123
Slowcoach SC123
Slowcoach SC123
Slowcoach SC555
Slowcoach SC555
Slowcoach SC555
Slowcoach SC555
Slowcoach SC111
SpeedyTram ST111
SpeedyTram ST111
SpeedyTram ST222
SpeedyTram ST222
SpeedyTram ST222
SpeedyTram ST222
SpeedyTram ST333
SpeedyTram ST444

我想计算路线,然后仅显示最受欢迎的 2 条路线,按巴士分组:

Bus Route Count
Slowcoach SC555 4
Slowcoach SC123 3
SpeedyTram ST222 4
SpeedyTram ST111 2

到目前为止我有以下内容:

SELECT Bus, Route, COUNT(Route) 
FROM my_table
GROUP BY Bus, Route
ORDER BY Bus, COUNT DESC

我查看了 Rank / Partition /Limit,但我无法使 COUNT 字段起作用,也无法计算出正确的语法。

解决方案有点扭曲:

  WITH list AS
    (
    SELECT Bus, Route, COUNT(Route) AS count
    FROM test
    GROUP BY Bus, Route
    ), consolidated_list AS
    (
    SELECT jsonb_agg(row_to_json(l.*) ORDER BY l.count DESC) AS list
      FROM list AS l
     GROUP BY Bus
    )
    SELECT j->>'bus' AS bus
         , j->>'route' AS Route
         , j->>'count' AS count
      FROM consolidated_list AS l
     CROSS JOIN LATERAL jsonb_path_query (l.list :: jsonb, '$[0,1]') AS j

结果:

bus         route   count
Slowcoach   SC555   4
Slowcoach   SC123   3
SpeedyTram  ST222   4
SpeedyTram  ST111   2

详见dbfiddle

分组并计数 (ti) 然后 order/assign 公交车位置 (tx) 和 select 这些位置 <= 2.

select bus, route, cnt
from
(
  select *, row_number() over (partition by bus order by cnt desc) r
  from 
  (
    select bus, route, count(*) cnt 
    from the_table
    group by bus, route
  ) ti 
) tx
where r <= 2;

SQL fiddle

同样使用 titx 作为 CTE,可能更清晰、更易读:

with ti as
(
  select bus, route, count(*) cnt from the_table group by bus, route
), 
tx as
(
  select *, row_number() over (partition by bus order by cnt desc) r from ti
)
select bus, route, cnt from tx
where r <= 2;

编辑
如果您需要带领带的结果,请使用 dense_rank() 而不是 row_number().