sql - 应用 GROUP BY 后检查相同数量(棘手的场景)

标签 sql oracle

我正在尝试检查特定帐号和不同组织的输出是否相同,并在 Oracle 中显示差异

假设我有一个名为 myTable 的表,它包含 2 个字段:accountnumberorg_id

仅存在 3 个 org_id:81、281 和 404

image

数据集:

|accountnumber|org_id|
|4435354      |81    |
|4435354      |281   |
|4435354      |404   |
|3333333      |81    |
|3333333      |281   |
|4444444      |81    |
|4444444      |81    |
|4444444      |281   |
|4444444      |404   |

我想查找每个 org_id 没有确切金额的所有不同帐户

例如:

account 4435354 has 1 row for org_id 81, 1 row for org_281 and 1 row for org_id 404, so in this case it is correct

account 3333333 has 1 row for org_id 81, 1 row for org_281 and none for 404 so there exist a discrepancy

account 4444444 has 2 rows for org_id 81, 1 row for org_281 and 1 row for org_id 404, so there exist a discrepancy

期望的输出:

ACCOUNTNUMBER| ORG_ID|COUNT(*)
|3333333      |  81   |1
|3333333      |  281  |1
|3333333      |  404  |0
|4444444      |  81   |2
|4444444      |  281  |1
|4444444      |  404  |1

如何在 Oracle 中实现类似的功能?


编辑#1

此场景是有效的,不应显示

|9999999      |81    |
|9999999      |81    |
|9999999      |81    |
|9999999      |404   |
|9999999      |404   |
|9999999      |404   |
|9999999      |281   |
|9999999      |281   |
|9999999      |281   |

这是正确的,因为该帐号的每个 org_id 都有 3 个,而且它是正确的

最佳答案

您已经在这里问了几乎相同的问题:Find the discrepancies in sql (tricky situation) (你还没有选择正确的答案)

只需添加 count(*)count(distinct org_id):DBFiddle

select
  accountnumber
  ,count(org_id) cnt
  ,count(distinct org_id) cnt_distinct
  ,listagg(org_id,',')within group(order by org_id) orgs
  ,listagg(distinct org_id,',')within group(order by org_id) orgs_distinct
from mytable
group by accountnumber;

结果:

ACCOUNTNUMBER        CNT CNT_DISTINCT ORGS          ORGS_DISTINCT
------------- ---------- ------------ ------------- --------------
      3333333          2            2 81,281        81,281
      4435354          3            3 81,281,404    81,281,404
      4444444          4            3 81,81,281,404 81,281,404

如果您确实需要单独使用所有行: DBFiddle

select
  accountnumber
  ,org_id
  ,count(org_id)          over(partition by accountnumber) cnt
  ,count(distinct org_id) over(partition by accountnumber) cnt_distinct
  ,listagg(org_id,',')within group(order by org_id)
     over(partition by accountnumber)
       as orgs
  ,listagg(distinct org_id,',')within group(order by org_id) 
     over(partition by accountnumber)
       as orgs_distinct
from mytable;

结果:

ACCOUNTNUMBER     ORG_ID        CNT CNT_DISTINCT ORGS          ORGS_DISTINCT
------------- ---------- ---------- ------------ ------------- --------------
      3333333         81          2            2 81,281        81,281
      3333333        281          2            2 81,281        81,281
      4435354         81          3            3 81,281,404    81,281,404
      4435354        281          3            3 81,281,404    81,281,404
      4435354        404          3            3 81,281,404    81,281,404
      4444444         81          4            3 81,81,281,404 81,281,404
      4444444         81          4            3 81,81,281,404 81,281,404
      4444444        281          4            3 81,81,281,404 81,281,404
      4444444        404          4            3 81,81,281,404 81,281,404

Listagg documentation :

For a specified measure, LISTAGG orders data within each group specified in the ORDER BY clause and then concatenates the values of the measure column.

更新:您只需添加谓词即可过滤不想输出的行: DBFiddle 3

select *
from (
    select
      accountnumber
      ,org_id
      ,count(org_id)          over(partition by accountnumber) cnt
      ,count(distinct org_id) over(partition by accountnumber) cnt_distinct
      ,listagg(org_id,',')within group(order by org_id)
         over(partition by accountnumber)
           as orgs
      ,listagg(distinct org_id,',')within group(order by org_id) 
         over(partition by accountnumber)
           as orgs_distinct
    from mytable) v
where cnt<>3;

结果:

ACCOUNTNUMBER     ORG_ID        CNT CNT_DISTINCT ORGS          ORGS_DISTINCT
------------- ---------- ---------- ------------ ------------- --------------
      3333333         81          2            2 81,281        81,281
      3333333        281          2            2 81,281        81,281
      4444444         81          4            3 81,81,281,404 81,281,404
      4444444         81          4            3 81,81,281,404 81,281,404
      4444444        281          4            3 81,81,281,404 81,281,404
      4444444        404          4            3 81,81,281,404 81,281,404

关于sql - 应用 GROUP BY 后检查相同数量(棘手的场景),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71229955/

相关文章:

performance - 有没有办法限制或限制 Oracle 中用户使用的资源?

mysql更新查询检查数据是否更新或匹配

mysql - 插入新行或删除旧行(如果已存在)

mysql - 建立不同物理数据库之间的关系

具有不同值的报告区域上的 Oracle APEX 工具提示

java - Android:如何使用 Android Java 代码连接 oracle 数据库?

java - executeUpdate 返回行数而不是受影响的行数

sql - SQL Server 中的嵌套表类型

sql - 如何在 Teradata SQL 上根据某些条件保留特定组的第一行?

java - 如何在 Hibernate 中使用 Oracle XMLTYPE