【问题标题】:Sql Hierarchy query with two tables带有两个表的 Sql 层次结构查询
【发布时间】:2016-10-02 22:09:44
【问题描述】:

我有两个单独的 oracle 表,每个表都有一个层次结构。它们由 ACCOUNT_TYPE 键关联。 表1的定义是这样的。

CREATE TABLE ACCOUNTS(
    ACCOUNT_CODE VARCHAR2(6),
    ACCOUNT_PRED VARCHAR2(6),
    ACCOUNT_TYPE VARCHAR2(6),
    ACCOUNT_TITLE VARCHAR2(100)
    );

表2定义是这样的

 CREATE TABLE ACCOUNT_TYPES(
    ACCOUNT_TYPE  VARCHAR2(6),
    ACCOUNT_NUMBER_PRED VARCHAR2(6),
    ACCOUNT_TITLE VARCHAR(100)
    );

表1包含以下数据

Insert into HR.ACCOUNTS (ACCOUNT_CODE,ACCOUNT_PRED,ACCOUNT_TYPE,ACCOUNT_TITLE) values ('0001',null,'11','xxxx');
Insert into HR.ACCOUNTS (ACCOUNT_CODE,ACCOUNT_PRED,ACCOUNT_TYPE,ACCOUNT_TITLE) values ('0042','0070','13','xxxx');
Insert into HR.ACCOUNTS (ACCOUNT_CODE,ACCOUNT_PRED,ACCOUNT_TYPE,ACCOUNT_TITLE) values ('0054','0110','13','xxxx');
Insert into HR.ACCOUNTS (ACCOUNT_CODE,ACCOUNT_PRED,ACCOUNT_TYPE,ACCOUNT_TITLE) values ('0056','0070','13','xxxx');
Insert into HR.ACCOUNTS (ACCOUNT_CODE,ACCOUNT_PRED,ACCOUNT_TYPE,ACCOUNT_TITLE) values ('0070',null,'13','xxxx');
Insert into HR.ACCOUNTS (ACCOUNT_CODE,ACCOUNT_PRED,ACCOUNT_TYPE,ACCOUNT_TITLE) values ('0110',null,'13','xxxx');
Insert into HR.ACCOUNTS (ACCOUNT_CODE,ACCOUNT_PRED,ACCOUNT_TYPE,ACCOUNT_TITLE) values ('0172','0171','13','xxxx');
Insert into HR.ACCOUNTS (ACCOUNT_CODE,ACCOUNT_PRED,ACCOUNT_TYPE,ACCOUNT_TITLE) values ('0060','0001','11','XXXX');

表二包含以下数据

REM INSERTING into ACCOUNT_TYPES
SET DEFINE OFF;
Insert into ACCOUNT_TYPES (ACCOUNT_TYPE,ACCOUNT_NUMBER_PRED,ACCOUNT_TITLE) values ('10',null,'xxxx');
Insert into ACCOUNT_TYPES (ACCOUNT_TYPE,ACCOUNT_NUMBER_PRED,ACCOUNT_TITLE) values ('11','10','xxxx');
Insert into ACCOUNT_TYPES (ACCOUNT_TYPE,ACCOUNT_NUMBER_PRED,ACCOUNT_TITLE) values ('12','10','xxxx');
Insert into ACCOUNT_TYPES (ACCOUNT_TYPE,ACCOUNT_NUMBER_PRED,ACCOUNT_TITLE) values ('13','10','xxxx');
Insert into ACCOUNT_TYPES (ACCOUNT_TYPE,ACCOUNT_NUMBER_PRED,ACCOUNT_TITLE) values ('14','10','xxxx');
Insert into ACCOUNT_TYPES (ACCOUNT_TYPE,ACCOUNT_NUMBER_PRED,ACCOUNT_TITLE) values ('15','10','xxxx');
Insert into ACCOUNT_TYPES (ACCOUNT_TYPE,ACCOUNT_NUMBER_PRED,ACCOUNT_TITLE) values ('16','10','xxxx');
Insert into ACCOUNT_TYPES (ACCOUNT_TYPE,ACCOUNT_NUMBER_PRED,ACCOUNT_TITLE) values ('17','10','xxxx');
Insert into ACCOUNT_TYPES (ACCOUNT_TYPE,ACCOUNT_NUMBER_PRED,ACCOUNT_TITLE) values ('18','10','xxxx');
Insert into ACCOUNT_TYPES (ACCOUNT_TYPE,ACCOUNT_NUMBER_PRED,ACCOUNT_TITLE) values ('19','10','xxxx');
Insert into ACCOUNT_TYPES (ACCOUNT_TYPE,ACCOUNT_NUMBER_PRED,ACCOUNT_TITLE) values ('1A','10','xxxx');

我可以像这样运行层次结构查询

SELECT lpad(' ', (level -1) * 3) || ACCOUNT_CODE  AS ACCOUNT_CODE,
             ACCOUNT_TITLE TITLE,
             ACCOUNT_PRED PRED,
             ACCOUNT_TYPE ATYPE
     FROM    ACCOUNTS
  CONNECT BY PRIOR ACCOUNT_CODE = ACCOUNT_PRED
  START WITH       ACCOUNT_PRED  IS NULL

还有一个这样的

SELECT lpad(' ', (level -1) * 3) ||ACCOUNT_TYPE ,
             ACCOUNT_TITLE,
             ACCOUNT_NUMBER_PRED
     FROM    ACCOUNT_TYPES
  CONNECT BY PRIOR ACCOUNT_TYPE = ACCOUNT_NUMBER_PRED
  START WITH  ACCOUNT_NUMBER_PRED  IS NULL;

查询一个基本上会返回这些值

0001
   0060
0070
 0042
 0056
0110
 0054

我正在尝试在层次结构中首先获取帐户类型 所以相反,我试图产生这个结果。

11
  0001
     0060
13
  0070
     0042
     0056
  0110
     0054

任何人都可以帮我生成一个查询,该查询基本上包括作为第一级的帐户类型,然后在它们之下是将在这些帐户下报告的一组帐户。

任何帮助将不胜感激。

【问题讨论】:

  • 删除 MySQL 标签,因为您使用的是 Oracle 支持的 CONNECT WITH

标签: sql oracle


【解决方案1】:

如果帐户和帐户类型的键是分离的,则此查询将使用层次结构上的顶级帐户类型级别丰富您的数据集。 (如果帐户类型的键可以相同 - 添加一些前缀来区分)。

select ACCOUNT_CODE, nvl(ACCOUNT_PRED,ACCOUNT_TYPE) ACCOUNT_PRED,  ACCOUNT_TITLE from   ACCOUNTS
union all
select ACCOUNT_TYPE ACCOUNT_CODE, null ACCOUNT_PRED, ACCOUNT_TITLE from   ACCOUNT_TYPES where  ACCOUNT_TYPE in (
  select ACCOUNT_TYPE from   ACCOUNTS where ACCOUNT_PRED is NULL)

请注意,上半部分使用NVL简单地从顶层(null)切换到相应的帐户类型。第二部分添加缺少的帐户类型级别。

使用它作为来源,只需应用您的分层查询。

with acc as (     
select ACCOUNT_CODE, nvl(ACCOUNT_PRED,ACCOUNT_TYPE) ACCOUNT_PRED,  ACCOUNT_TITLE from   ACCOUNTS
union all
select ACCOUNT_TYPE ACCOUNT_CODE, null ACCOUNT_PRED, ACCOUNT_TITLE from   ACCOUNT_TYPES where  ACCOUNT_TYPE in (
  select ACCOUNT_TYPE from   ACCOUNTS where ACCOUNT_PRED is NULL)
)
SELECT lpad(' ', (level -1) * 3) || ACCOUNT_CODE  AS ACCOUNT_CODE, 
             ACCOUNT_TITLE TITLE,
             ACCOUNT_PRED PRED 
     FROM    ACC 
  CONNECT BY PRIOR ACCOUNT_CODE = ACCOUNT_PRED
  START WITH     ACCOUNT_PRED  IS NULL;

按预期产生结果:

ACCOUNT_CODE    TITLE  PRED 
--------------- ------ ------
11              xxxx          
   0001         xxxx   11     
      0060      XXXX   0001   
13              xxxx          
   0070         xxxx   13     
      0042      xxxx   0070   
      0056      xxxx   0070   
   0110         xxxx   13     
      0054      xxxx   0110

【讨论】:

  • 感谢 Marmite,真是太棒了!非常感谢您的回复。
【解决方案2】:

进行查询,为您预测层次结构所需的数据:

select ACCOUNT_CODE, nvl(ac.ACCOUNT_PRED, ac.ACCOUNT_TYPE)
from ACCOUNT_TYPES at
join ACCOUNTS ac on (at.ACCOUNT_TYPE = ac.ACCOUNT_TYPE)

这将为您提供一个帐户“表”(数据集),您的 pred 可能是帐户类型。现在您可以在两个表之间建立一个联合,并对结果进行层次结构:

select *
from 
 (SELECT ACCOUNT,PRED
 FROM    ACCOUNT_TYPES

 union all

 select ACCOUNT, nvl(ac.ACCOUNT_PRED, ac.ACCOUNT_TYPE) as PRED
 from ACCOUNT_TYPES at
 join ACCOUNTS ac on (at.ACCOUNT_TYPE = ac.ACCOUNT_TYPE))
CONNECT BY PRIOR ACCOUNT = PRED
START WITH  PRED  IS NULL

说实话,我还没有运行它,所以我不确定它是否有效,但这个想法应该没问题。希望有帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-23
    • 1970-01-01
    • 1970-01-01
    • 2017-01-27
    相关资源
    最近更新 更多