table 中不存在于另一个中的值(通过单独的组列)

values from table that not exist in another (by seperate group column)

这个问题是关于 oracle 数据库的。

我有一个包含几列的 table (T1):

group id price
A 1 50
A 5 40
B 4 54
C 1 33
C 6 33
D 5 13
D 3 4

还有一个有 2 列的 table (T2):

id description
1 aaa
2 bbb
3 ccc
4 ddd
5 eee
6 fff
7 ggg

此 table (t2) 中的 ID 是唯一的。 两个 table 之间的连接是通过“id”列。

我需要检查 T1 中的每个 (!) 组(A、B、C、D), 来自 T2 的“id”中的哪个 - 在 T1 中找不到该组, 并且结果需要是:group + id(该组中不存在)

对于上面 table 的例子,我希望得到这个结果:

group id
A 2
A 3
A 4
A 6
A 7
B 1
B 2
B 3
B 5
B 6
B 7
C 2
C 3
C 4
C 5
C 7
D 1
D 2
D 4
D 6
D 7

谢谢!

这里的想法是使用笛卡尔连接创建所有可能的记录组合,然后通过 left joinnot null

匹配所有组和 select 不存在的组
create table T1 (c1 varchar2(10), c2 number(10), c3 number(10))

 insert into T1 values('A',     1,  50);
 insert into T1 values('A',     5,  40);
 insert into T1 values('B',     4 , 54);
 insert into T1 values('C',     1,  33);
 insert into T1 values('C', 6,  33);
 insert into T1 values('D',     5,  13);
 insert into T1 values('D',     3,  4);

create table T2 (c6 number(10), c7 varchar2(10))

 insert into T2 values( 1,  'aaa');
 insert into T2 values( 2,  'bbb');
 insert into T2 values( 3,  'ccc');
 insert into T2 values( 4,  'ddd');
 insert into T2 values( 5,  'eee');
 insert into T2 values( 6,  'fff');
 insert into T2 values( 7,  'ggg');

 SELECT tx.c1, tx.c6, ty.c1
 FROM
     (select c1, c6 
      from 
          (select distinct c1 from T1) ta,
          (select distinct c6 from T2) tb) tx -- tx is the cartisian product
          left join 
          (select c1, c2 from T1 group by c1, c2) ty 
              on tx.c1 = ty.c1 and tx.c6 = ty.c2
WHERE 
    ty.c1 is null
ORDER BY 1, 2

这正是您要找的东西。 经过测试和验证

首先,找到所有可能的组合,然后确定其中不存在的组合:

WITH cteCombinations
 AS (SELECT DISTINCT T1."group", T2.ID
       FROM T1
       CROSS JOIN T2)
SELECT c."group", c.ID
  FROM cteCombinations c
  LEFT OUTER JOIN T1
    ON T1.ID = c.ID AND
       T1."group" = c."group"
  WHERE T1.ID IS NULL
  ORDER BY c."group", c.ID

CTE(通用 Table 表达式)使用 CROSS JOIN 来查找组和 ID 的所有唯一组合;然后 LEFT OUTER JOIN 用于确定 T1 中不存在的组合。

另一种方法是:

WITH cteCombinations
 AS (SELECT DISTINCT T1."group", T2.ID
       FROM T1
       CROSS JOIN T2)
SELECT c."group", c.ID
  FROM cteCombinations c
  WHERE (c."group", c.ID) NOT IN (SELECT "group", ID
                                    FROM T1)
  ORDER BY c."group", c.ID

这里我们使用相同的 CTE 来生成可能的组合,但我们使用 NOT IN 比较来确定哪些组合不存在于 table 中,而不是 LEFT OUTER JOIN T1.

db<>fiddle here

在 Oracle 中你可以使用 partitioned join

with a(grp, id, price) as (
  select 'A', 1, 50 from dual union all
  select 'A', 5, 40 from dual union all
  select 'B', 4, 54 from dual union all
  select 'C', 1, 33 from dual union all
  select 'C', 6, 33 from dual union all
  select 'D', 5, 13 from dual union all
  select 'D', 3, 4 from dual
)
, b (id, descr) as (
  select 1, 'aaa' from dual union all
  select 2, 'bbb' from dual union all
  select 3, 'ccc' from dual union all
  select 4, 'ddd' from dual union all
  select 5, 'eee' from dual union all
  select 6, 'fff' from dual union all
  select 7, 'ggg' from dual
)
select
  grp
  , id
from a
  partition by (grp)
  right join b
    using (id)
where a.price is null
order by grp, id
GRP | ID
:-- | -:
A   |  2
A   |  3
A   |  4
A   |  6
A   |  7
B   |  1
B   |  2
B   |  3
B   |  5
B   |  6
B   |  7
C   |  2
C   |  3
C   |  4
C   |  5
C   |  7
D   |  1
D   |  2
D   |  4
D   |  6
D   |  7

db<>fiddle here