sql - 当按其他列分组时,如何在特定列中选择具有非唯一值的行?
问题描述
我有一张tbl
这样的桌子:
| id | grp | pid | oid |
| -- | --- | --- | --- |
| 1 | 1 | 1 | 1 |
| 2 | 2 | 2 | 1 |
| 3 | 3 | 1 | 1 |
| 4 | 3 | 2 | 1 |
| 5 | 4 | 1 | 1 |
| 6 | 1 | 1 | 2 |
| 7 | 2 | 2 | 2 |
| 8 | 3 | 1 | 2 |
| 9 | 4 | 1 | 2 |
我正在尝试编写一个 PostgreSQL 查询,它选择给定 OID 中给定 GRP 的行,PID 的不同计数大于 1。对于上述情况,由于 PID 对 GRP 3 有两个不同的值(1 和 2) OID 1,它应该返回:
| id | grp | pid | oid |
| -- | --- | --- | --- |
| 3 | 3 | 1 | 1 |
| 4 | 3 | 2 | 1 |
我有一个使用 Python + Pandas 的解决方案,虽然这不太理想:
import pandas as pd
rows = pd.read_sql("SELECT * FROM tbl", db.engine)
output = pd.DataFrame(columns = rows.columns)
oids = rows['oid'].tolist()
for oid in oids:
oid_rows = rows[rows['oid'] == oid]
grps = oid_rows['grp'].tolist()
for grp in grps:
grp_rows = oid_rows[oid_rows['grp'] == grp]
if len(grp_rows) > 1:
output = pd.concat([output, grp_rows],axis=0)
print(output)
我更喜欢纯粹在 SQL 中执行此操作,本质上是一个类似于以下内容的查询:
SELECT * FROM tbl HAVING COUNT(pid) > 1 IN
(SELECT * FROM tbl GROUP BY grp, oid)
如何编写此查询?
解决方案
您可以使用exists
:
select t.*
from tbl t
where exists (select 1
from tbl t2
where t2.grp = t.grp and t2.oid = t.oid and
t2.id <> t.id
);
您还可以使用窗口函数——尽管这可能效率较低:
select t.*
from (select t.*, count(*) over (partition by grp, oid) as cnt
from tbl t
) t
where cnt >= 2;
推荐阅读
- c++ - DirectX 窗口媒体键没有响应
- android - onGetSentenceSuggestions 建议始终为空
- python - 在 python 的函数中使用 Iterable 和 numeric 作为输入
- python - 当多边形变得太小时时,带有 polycollection 的绘图会消失
- android - 当文本视图从屏幕隐藏时如何设置工具栏标题?
- c - 如果EOF,使程序停止从文件中读取并仅从其他文件中读取
- mongodb - Mongodb 对 $filter 和 $map 或 $unwind 的准确 $sum
- mysql - MYSQL max() 并按错误分组:only_full_group_by
- oracle - 如何创建 UPSERT 命令?
- azure - 如何在群集单击事件上缩放 Azure Maps 边界框?