从 SQL 到 SPL:从关系表里找出超集

mysql 库有 2 个表:袋子表、袋子物品关系表,有些袋子是其他袋子的超集。

bag

id

name

A

Bag A

B

Bag B

C

Bag C

D

Bag D

bag_item

id

bag_id

item_id

1

A

1

2

A

2

3

B

1

4

B

2

5

B

3

6

B

4

7

C

1

8

C

4

9

D

1

10

D

2

11

D

3

现在要找出每个袋子的超集:

base_bag_id

superset_bag_id

A

B

A

D

C

B

D

B

SQL:

SELECT
  base.id AS base_bag_id,
  s.id AS superset_bag_id
FROM bag base
JOIN bag s
   ON s.id <> base.id
  AND NOT EXiSTS (SELECT 1
    FROM bag_item bi
    WHERE bi.bag_id = base.id
      AND NOT EXISTS (SELECT 1
        FROM bag_item si
        WHERE si.item_id = bi.item_id
          AND si.bag_id = s.id
    )
);

这里需要两层循环遍历,SQL 要用三层嵌套配合 JOIN 和难懂的 EXISTS 实现集合运算,理解难度大。SPL 可以简单用二层循环配合直观的集合运算实现。https://try.esproc.com/splx?471


 A

1

$select * from bag_item.txt

2

=A1.group(bag_id; ~.(item_id):items)

3

=A2.news((b=bag_id, i=items, A2.select( b!=bag_id && i \ items==[]));

b:base_bag_id, bag_id:superset_bag)

A2:按袋子分组,但不汇总,每组是一个袋子以及袋子里物品的集合 items。

A3:两层循环计算出目标结果,\ 表示差集运算。

问题来源:https://stackoverflow.com/questions/78222276/find-supersets-of-association-database-table