求每组丢失物品的数量(ORACLE SQL)

Find the number of lost items in each group (ORACLE SQL)

假设我有以下 table 和这些记录

Table: COMPARE_INDIV

+----------+--------------+--------------+
| ID_GROUP | INDIV_ID_OLD | INDIV_ID_NEW |
+----------+--------------+--------------+
|        1 |          123 | 567          |
|        1 |          123 | null         |
|        1 |          123 | 123          |
|        2 |          891 | null         |
|        2 |          891 | 456          |
+----------+--------------+--------------+

我想将条目插入到名为 COUNTS 的 table 中,用于计算 COMPARE_INDIV table 中每个 GROUP_ID 丢失的 INDIV_ID_OLD 的数量。如果每个 GROUP_ID 的 INDIV_ID_NEW 列中不存在 INDIV_ID_OLD,则 INDIV_ID_OLD 将丢失。在这种情况下,计数 table 将如下所示。

Table:计数

+----------+------------+--+
| ID_GROUP | LOST_COUNT |  |
+----------+------------+--+
|        1 |          0 |  |
|        2 |          1 |  |
+----------+------------+--+

我该如何完成这样的事情?

如果我没理解错的话,你可以使用两级聚合:

select id_group, sum(1 - present) as missing
from (select id_group, indiv_id_old,
             max(case when individ_id_new = indiv_id_old then 1 else 0 end) as present
      from COMPARE_INDIV ci
      group by id_group, indiv_id_old
     ) ci
group by id_group;

类似,但只有一个聚合:

SQL> with compare_indiv (id_group, indiv_id_old, indiv_id_new) as
  2  -- sample data
  3    (select 1, 123, 567  from dual union all
  4     select 1, 123, null from dual union all
  5     select 1, 123, 123  from dual union all
  6     select 2, 891, null from dual union all
  7     select 2, 891, 456  from dual
  8    ),
  9  temp as
 10  -- SUM will be 0 if nothing matches
 11    (select id_group,
 12       sum(case when indiv_id_old = indiv_id_new then 1 else 0 end) sumon
 13     from compare_indiv
 14     group by id_group
 15    )
 16  -- final result
 17  select id_group,
 18    case when sumon = 0 then 1 else 0 end lost_count
 19  from temp
 20  /

  ID_GROUP LOST_COUNT
---------- ----------
         1          0
         2          1

SQL>

也许存在更好的形式,但这是适合您的一种解决方案

INSERT INTO COUNTS
SELECT A.ID_GROUP , sum(A.is_lost) LOST_COUNT
FROM
(
    SELECT  A.ID_GROUP ,  A.INDIV_ID_OLD
            ,NVL((
                SELECT 0
                FROM COMPARE_INDIV B
                WHERE   A.ID_GROUP      = B.ID_GROUP
                AND     A.INDIV_ID_OLD  = B.INDIV_ID_NEW
                AND     ROWNUM          = 1
            ),1) is_lost
    FROM        COMPARE_INDIV A
    GROUP BY A.ID_GROUP , A.INDIV_ID_OLD
) A
GROUP BY A.ID_GROUP