sql - 如何为postgresql中的每个用户返回具有最大值的类别?
问题描述
这是桌子
ID | 类别 | 价值 |
---|---|---|
1 | 一个 | 40 |
1 | 乙 | 20 |
1 | C | 10 |
2 | 一个 | 4 |
2 | 乙 | 7 |
2 | C | 7 |
3 | 一个 | 32 |
3 | 乙 | 21 |
3 | C | 2 |
我想要这样的结果
ID | 类别 |
---|---|
1 | 一个 |
2 | 乙 |
2 | C |
3 | 一个 |
解决方案
对于小表或每个用户只有很少的行,带有窗口函数的子查询rank()
(如The Impaler 所示)就可以了。对整个表进行顺序扫描,然后进行排序将是最有效的查询计划。
但是,对于每个用户多于几行的情况,这会变得越来越低效。
通常,您还有一个users
表,每个用户都有一个不同的行。如果您没有,请创建它!看:
我们可以将其用于可扩展性更好的替代查询——WITH TIES
在LATERAL JOIN
. 需要Postgres 13或更高版本。
SELECT u.id, t.*
FROM users u
CROSS JOIN LATERAL (
SELECT t.category
FROM tbl t
WHERE t.id = u.id
ORDER BY t.value DESC
FETCH FIRST 1 ROWS WITH TIES -- !
) t;
db<>在这里摆弄
看:
这可以使用多列索引来产生很好的效果 - 当然,它必须存在:
CREATE INDEX ON tbl (id, value);
或者:
CREATE INDEX ON tbl (id, value DESC);
通过以下方式可以实现更快的仅索引扫描:
CREATE INDEX ON tbl (id, value DESC, category);
或者(手头查询的最佳选择):
CREATE INDEX ON tbl (id, value DESC) INCLUDE (category);
假设value
是定义NOT NULL
的,或者我们必须使用DESC NULLS LAST
. 看:
为了将用户保留在 table 中没有任何行的结果中tbl
, user LEFT JOIN LATERAL (...) ON true
。看:
推荐阅读
- docker - 无法在 Linux 上使用 ElasticSearch 映射日志存储
- java - 自定义键盘中的 Android Speech to Text 功能
- mysql - mysql更新语句执行
- react-native - 尝试使用 Open Tok React Native 库时出错,otk_anvil.cpp:467
- mysql - kafka连接器更新rest api不更新接收器数据
- node.js - 使用聚合的计数总数
- python - 我们可以在python中将keras模型保存为二进制文件吗?
- c++ - 如何使 char* 指向 char[]?
- database - 在 kotlin 的房间数据库中添加新记录
- c# - 我们如何以编程方式更改无线蓝牙无线电电源管理 C#