首页 > 解决方案 > 根据特定逻辑从表中检索配置文件

问题描述

我需要根据以下标准从表中提取配置文件:

  1. 总共有5个ID。100、200、300、400 和 500
  2. 每个值 100、300 和 400 中至少有一个 ID 的配置文件。值 200 和 500 的 ID 甚至不应出现一次。
  3. 配置文件可以有多个 ID 值为 300 和 400,但只有一个 ID 值为 100。
  4. 配置文件将具有相同的 ID 300 和 400。即对于每个 ID 的值为 300,将有一个值为 400 的 ID。

例如

表 A

-------------------------
PROFILE_ID          ID
-------------------------
12345               100
12345               300
12345               400
23456               100
23456               300
23456               400
23456               300
23456               400
34567               100
34567               200
-------------------------

结果应获取 PROFILE_ID 12345 和 23456 而不是 34567。

对于如何为此构建查询有一个清晰的想法,我非常困惑和空白。请帮忙。

标签: oracle

解决方案


对于您发布的示例数据:

SQL> select * From test;

PROFILE_ID         ID
---------- ----------
     12345        100
     12345        300
     12345        400
     23456        100
     23456        300
     23456        400
     23456        300
     23456        400
     34567        100
     34567        200

10 rows selected.

一种选择是逐个规则地进行,每个 CTE 检索满足特定规则的数据。最终结果是这些PROFILE_IDs 的交集。

SQL> with
  2  rule2 as  -- don't allow IDs 200 nor 500
  3    (select profile_id
  4     from test
  5     where profile_id not in (select profile_id
  6                              from test
  7                              where id in (200, 500)
  8                             )
  9    ),
 10  rule3 as  -- there can be only one ID = 100 for each PROFILE_ID
 11    (select profile_id
 12     from (select profile_id,
 13             sum(case when id = 100 then 1 else 0 end) cnt_100
 14           from test
 15           group by profile_id
 16          )
 17     where cnt_100 = 1
 18    ),
 19  rule4 as  -- number of IDs 300 and 400 has to be equal and greater than 0
 20    (select profile_id
 21     from (select profile_id,
 22             sum(case when id = 300 then 1 else 0 end) cnt_300,
 23             sum(case when id = 400 then 1 else 0 end) cnt_400
 24           from test
 25           group by profile_id
 26          )
 27     where cnt_300  = cnt_400
 28       and cnt_300 > 0
 29    )
 30  select profile_id from rule2
 31  intersect
 32  select profile_id from rule3
 33  intersect
 34  select profile_id from rule4;

PROFILE_ID
----------
     12345
     23456

SQL>

推荐阅读