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;
同样使用 ti
和 tx
作为 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()
.
我有一些数据格式如下:
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;
同样使用 ti
和 tx
作为 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()
.