【问题标题】:Hierarchical query with one to many relationship具有一对多关系的分层查询
【发布时间】:2023-03-14 08:30:01
【问题描述】:

我有三张桌子; d_algorithme:

   ID_ALGO VERSION_ALGO LIBELLE_ALGO                                     
---------- ------------ --------------------------------------------------
       300 A300V1       Algo_300_V1                                       
       301 A301V1       Algo_301_V1                                       
       302 A302V1       Algo_302_V1                                       

d_algo_ope:

NUM_OPERATION    ID_ALGO VERSION_ALGO TYP_OPERATION  NUM_ORDRE
------------- ---------- ------------ ------------- ----------
          300        301 A301V1                   3          1
            1        300 A300V1                   3          1
          301        302 A302V1                   3          1

最后是d_algo_maj:

NUM_MISE_A_JOUR    ID_ALGO VERSION_ALGO
--------------- ---------- ------------
             11        301 A301V1      

我想创建一个查询,给出如下结果:

id_algo   | version_algo |  has_maj
300       | A300V1       |  0       
301       | A301V1       |  1
302       | A302V1       |  1 

前两列来自d_algorithmehas_maj 是 0 还是 1,这取决于在 d_algo_maj 中是否直接或间接引用了算法。间接引用是通过一个或多个 d_algo_ope 记录,它们一起形成一个层次结构。

对于显示的示例数据:

  • 300:id_algo = 1 没有算法或d_algo_ope 记录,id_algo = 300 没有d_algo_maj 记录。
  • 301:有一个d_algo_maj 记录与id_algo = 301(足以使has_maj 列设置为1)。
  • 302:没有d_algo_majid_algo = 302 的记录。但是有一个d_algo_ope 记录与num_operation = 301id_algo = 302,这意味着302 算法引用301 算法(它有一个maj),因此has_maj 列应该设置为1。

这里是 DDL 和 DML 以及其他细节(从我在现实中得到的简化):

-- DDL -----------------------------

-- d_algorithme
CREATE TABLE D_ALGORITHME 
(
  ID_ALGO NUMBER(10, 0) NOT NULL 
, VERSION_ALGO VARCHAR2(6 BYTE) NOT NULL 
, LIBELLE_ALGO VARCHAR2(50 BYTE) NOT NULL 
) ;

ALTER TABLE D_ALGORITHME
ADD CONSTRAINT IX_D_ALGORITHME PRIMARY KEY 
(
  ID_ALGO 
, VERSION_ALGO 
);

-- d_algo_ope
CREATE TABLE D_ALGO_OPE 
(
  NUM_OPERATION NUMBER(10, 0) NOT NULL 
, ID_ALGO NUMBER(10, 0) NOT NULL 
, VERSION_ALGO VARCHAR2(6 BYTE) NOT NULL 
, TYP_OPERATION NUMBER(6, 0) NOT NULL 
, NUM_ORDRE NUMBER(10, 0) NOT NULL 
); 

ALTER TABLE D_ALGO_OPE
ADD CONSTRAINT IX_D_ALGO_OPE PRIMARY KEY 
(
  ID_ALGO 
, VERSION_ALGO 
, NUM_ORDRE 
) ;

-- d_algo_maj
CREATE TABLE D_ALGO_MAJ 
(
  NUM_MISE_A_JOUR NUMBER(10, 0) NOT NULL 
, ID_ALGO NUMBER(10, 0) NOT NULL 
, VERSION_ALGO VARCHAR2(6 BYTE) NOT NULL 
) 
;

ALTER TABLE D_ALGO_MAJ
ADD CONSTRAINT IX_D_ALGO_MAJ PRIMARY KEY 
(
  ID_ALGO 
, VERSION_ALGO 
, NUM_MISE_A_JOUR 
)
;


-- DML ----------------


REM INSERTING into D_ALGORITHME


Insert into D_ALGORITHME (ID_ALGO,VERSION_ALGO,LIBELLE_ALGO) 
    values ('300','A300V1','Algo_300_V1');
Insert into D_ALGORITHME (ID_ALGO,VERSION_ALGO,LIBELLE_ALGO) 
    values ('301','A301V1','Algo_301_V1');
Insert into D_ALGORITHME (ID_ALGO,VERSION_ALGO,LIBELLE_ALGO) 
    values ('302','A302V1','Algo_302_V1');



REM INSERTING into D_ALGO_OPE

Insert into D_ALGO_OPE 
  (NUM_OPERATION,ID_ALGO,VERSION_ALGO,TYP_OPERATION,NUM_ORDRE) 
values ('300','301','A301V1','3','1');
Insert into D_ALGO_OPE (NUM_OPERATION,ID_ALGO,VERSION_ALGO,TYP_OPERATION,NUM_ORDRE) 
    values ('1','300','A300V1','3','1');
Insert into D_ALGO_OPE (NUM_OPERATION,ID_ALGO,VERSION_ALGO,TYP_OPERATION,NUM_ORDRE) 
    values ('301','302','A302V1','3','1');



REM INSERTING into D_ALGO_MAJ

Insert into D_ALGO_MAJ (NUM_MISE_A_JOUR,ID_ALGO,VERSION_ALGO) 
    values ('11','301','A301V1');

【问题讨论】:

  • 通常的连接可能不足以实现这一点,因为有很多级别由第三个表链接,即 d_algo_ope。
  • 不确定我是否理解这三个表是如何相关的,或者它们是如何形成层次结构的。 ID/version 1/1 和 2/2 在 d_algo_maj 中都有记录,那为什么第一个是间接的呢? d_algo_ope 是从哪里来的?
  • @AlexPoole 我希望这个链接中的图片能解释更多
  • 提前感谢您的帮助

标签: sql oracle hierarchical-query


【解决方案1】:

如果我了解您在做什么以及表之间的链接,那么我认为您可以使用recursive subquery factoring 获得您想要的结果(假设您使用的是 11gR2 或更高版本):

with r (id_algo, version_algo, has_maj, last_id_algo, last_version_algo) as (
  select da.id_algo, da.version_algo, decode(dm.id_algo, null, 0, 1),
    da.id_algo, da.version_algo
  from d_algorithme da
  left join d_algo_maj dm
  on dm.id_algo = da.id_algo
  and dm.version_algo = da.version_algo
  union all
  select dao.id_algo, dao.version_algo, decode(dm.id_algo, null, 0, 1),
    dao.id_algo, dao.version_algo
  from r
  join d_algo_ope dao
  on dao.id_algo = r.last_id_algo
  and dao.version_algo = r.last_version_algo
  left join d_algo_maj dm
  on dm.id_algo = dao.num_operation
)
cycle id_algo, version_algo set is_cycle  to 1 default 0
select id_algo, version_algo, max(has_maj) as has_maj
from r
group by id_algo, version_algo
order by id_algo, version_algo;

   ID_ALGO VERSION_ALGO    HAS_MAJ
---------- ------------ ----------
       300 A300V1                0
       301 A301V1                1
       302 A302V1                1

r CTE 有一个锚成员,它将d_algorithme 行外连接到d_algo_maj,并使用解码在该级别生成一个标志,或者为零或一。该部分自行运行将得到:

   ID_ALGO VERSION_ALGO    HAS_MAJ LAST_ID_ALGO LAST_VERSION_ALGO
---------- ------------ ---------- ------------ -----------------
       300 A300V1                0          300 A300V1           
       301 A301V1                1          301 A301V1           
       302 A302V1                0          302 A302V1           

然后递归成员查找任何匹配的 d_aldo_ope 记录,并以相同的方式将 that 外连接到 d_algo_maj,得到相同的标志。这部分本身会得到:

   ID_ALGO VERSION_ALGO    HAS_MAJ LAST_ID_ALGO LAST_VERSION_ALGO
---------- ------------ ---------- ------------ -----------------
       300 A300V1                0          300 A300V1           
       301 A301V1                0          301 A301V1           
       302 A302V1                1          302 A302V1           

但如果您的级别比示例数据中显示的多,则递归。

通过查找每个 ID/版本的聚合 max(has_maj) 将它们组合起来意味着任何级别的匹配主要记录都会给出 1 的总体标志值,如果根本没有匹配项,您只会得到 0 - 这只会发生使用此数据获取 ID 300。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-21
    • 1970-01-01
    • 2019-08-31
    • 2016-02-24
    相关资源
    最近更新 更多