【问题标题】:How to select rows with non-unique values in a specific column when grouped by other columns?当按其他列分组时,如何在特定列中选择具有非唯一值的行?
【发布时间】:2020-12-10 13:11:43
【问题描述】:

我有一张这样的桌子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 有两个不同的值(1 和 2) OID 1 中的 GRP 3,它应该返回:

| 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)

如何编写此查询?

【问题讨论】:

    标签: sql postgresql group-by


    【解决方案1】:

    你可以使用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;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-05
      • 1970-01-01
      • 2013-01-02
      • 2015-11-21
      • 1970-01-01
      • 2017-08-29
      相关资源
      最近更新 更多