SQL 自连接和聚合

标签 sql postgresql

我在 postgres 中有一个具有以下结构的表

表格路径: 乘客、出发地、目的地、日期、月份、年份

我想根据一年内在一条路线上旅行的乘客数量找到前 3 条路线。 一条路线上的乘客总数(A <-> B) = 乘客总数(A -> B) + 乘客总数( B->A )

聚合路线上乘客数量的最佳/最佳方式是什么,表格行数约为 1.5 亿行。

谢谢

最佳答案

有两种方法可以做到这一点。一种是聚合,另一种是连接。

select least(origin, dest) as od1, greatest(origin, dest) as od2, sum(passengers) as numpassengers
from path t
group by least(origin, dest), greatest(origin, dest)
order by numpassengers
limit 3;

另一种是自连接。如果每个方向只有一行,则可以不聚合:

select p1.origin, p1.dest, p1.passengers + p2.passengers as numpassengers
from path p1 join
     path pt2
     on p1.origin = p2.dest and p1.dest = p2.origin
where p1.origin < p1.dest
order by numpassengers desc
limit 3;

否则,您需要自连接和聚合,因此第一种方法可能更快:

select p1.origin, p1.dest, sum(p1.passengers + p2.passengers) as numpassengers
from path p1 join
     path pt2
     on p1.origin = p2.dest and p1.dest = p2.origin
where p1.origin < p1.dest
group by p1.origin, p1.dest
order by numpassengers desc
limit 3;

我不知道哪个效率更高。但是,我怀疑按总和计算的前 3 条路线会在每个方向的前 100 名中。如果是这样,在 numpassengers 上建立一个索引,然后尝试:

select least(origin, dest) as od1, greatest(origin, dest) as od2, sum(passengers) as numpassengers
from path t cross join
     (select min(passengers) as cutoff
      from (select distinct passengers
            from path
            order by passengers desc
            limit 100
           ) t
     ) minp
where numpassengers >= minp.cutoff
group by least(origin, dest), greatest(origin, dest)
order by numpassengers
limit 3;

截断的计算应该只使用索引,大大减少其余查询的负载。

编辑:

如果您没有least()greatest(),只需使用case 语句:

select (case when origin < dest then origin else dest end) as od1,
       (case when origin < dest then dest else origin end)  as od2,
       sum(passengers) as numpassengers
from path t
group by 1, 2
order by numpassengers
limit 3;

您可以在group by 中重复case 语句。但是 Amazon Redshift 允许您在 group by 子句中引用列别名或位置。

关于SQL 自连接和聚合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21530049/

相关文章:

mysql - 检查与您的 mysql 服务器版本相对应的手册,了解在 '( - 附近使用的正确语法

java - SQL 查询性能、存档与状态更改

mysql - 在 MySQL 中使用字符串的数字组件对字符串进行数字排序的首选方法是什么?

postgresql - pg_dumpall - Azure Database for PostgreSQL - 数据库 "azure_maintenance"的权限被拒绝

python - 来自 Python 的 Postgres : can I fetch N rows per time in a loop?

postgresql - 使用动态键在 JSON 字段上建立索引

mysql - 使用 JOIN 从 2 个表进行映射

mysql - SQL select 条件复杂

sql - 如果尝试对锁定行的父级进行级联删除,PostgreSQL 会发生什么情况?

postgresql - Postgres : Optimising concurrent same row updates