使用多个表进行Oracle层次查询,其中每个表代表一个级别。

huangapple go评论68阅读模式
英文:

Using multiple tables for an Oracle hierarchy query where each table represents a level

问题

我在研究创建一个用于 Oracle 数据库的分层 SQL 查询的方法,其中 Table1 和 Table2 之间存在多对一关系,Table2 和 Table3 之间也存在多对一关系,Table1 是 Table2 的父表,Table2 是 Table3 的父表。

我尝试创建一个查询,其中 Table1 代表 LEVEL 1,Table2 代表 LEVEL2,Table3 代表 Oracle 的 LEVEL 3 伪列。

简化的表结构如下,其中 TABLE1、TABLE2 和 TABLE3 各自都有唯一的列和它们自己的唯一 ID 和描述。

例如,想象一下 Table1 代表一个州,Table2 代表一个城市,Table3 代表一个邮编 - 它们都有自己独特的属性,一个州有很多城市,一个城市有很多邮编。

TABLE1(id (PK), t1name, description)
TABLE2(id (PK), t2name, table1ID (FK), description, var1, var2)
TABLE3(id (PK), t3name, table2ID (FK), description, var3, var4)

我尝试使用类似以下的查询,但 LEVEL 伪列始终为 '1',CONNECT_BY_ISLEAF 伪列也为 '1':

WITH alltabs as
    (Select 'T1' as src, table1.ID, NULL AS parent1Id, NULL as parent2Id, table1.name as name
    from table1
    union
    Select 'T2' as src, table2.ID, table2.table1Id, NULL as parent2Id, table2.name as name
    from table2
    union
    Select 3 as src, table3.ID, NULL AS parent1Id, table3.table2id, table3.name as name
    from table3)
Select LEVEL, src, parent1Id, parent2Id, name, CONNECT_BY_ISLEAF
from alltabs
connect by (id = parent1Id and (src = 'T1' or src = 'T2'))
        or (id = parent2Id AND (src = 'T2' or src = 'T3'))

我希望得到的结果是 LEVEL 伪列对于 Table1 为 '1',对于 Table2 为 '2',对于 Table3 为 '3'。

英文:

I'm researching ways to create a hierarchical SQL query for my Oracle database where Table1 and Table2 have a many-to-one relationship, and Table2 and Table3 have a many-to-one relationship and where Table1 is the parent of Table2, and Table2 is the parent of Table3.

I'm trying to create a query where Table1 represents LEVEL 1, Table2 represents LEVEL2, and Table3 represents LEVEL 3 in Oracle's LEVEL pseudocolumn.

A simplified table structure is as follows, where TABLE1, TABLE2, and TABLE3 each have columns that are unique to them and their own unique IDs and descriptions.

For example, imagine Table1 represent a State, Table2 represents a City, and Table3 represents a Zip code - these all have their own unique properties, and a State has many Cities, and a City has many Zip Codes.

TABLE1(id (PK), t1name, description)
TABLE2(id (PK), t2name, table1ID (FK), description, var1, var2)
TABLE3(id (PK), t3name, table2ID (FK), description, var3, var4)

I've tried using a query like this but the LEVEL pseudocolumn is always '1' and the CONNECT_BY_ISLEAF pseudocolumn is also '1':

WITH alltabs as
    (Select 'T1' as src, table1.ID, NULL AS parent1Id, NULL as parent2Id, table1.name as name
    from table1
    union
    Select 'T2' as src, table2.ID, table2.table1Id, NULL as parent2Id, table2.name as name
    from table2
    union
    Select 3 as src, table3.ID, NULL AS parent1Id, table3.table2id, table3.name as name
    from table3)
Select LEVEL, src, parent1Id, parent2Id, name, CONNECT_BY_ISLEAF
from alltabs
connect by (id = parent1Id and (src = 'T1' or src = 'T2'))
        or (id = parent2Id AND (src = 'T2' or src = 'T3'))

The result I'm looking for is one where the LEVEL pseudocolumn is '1' for Table1, '2' for Table2, and '3' for Table3.

Any guidance would be appreciated - I'm also open to changing the table structure. Thank you!

答案1

得分: 2

只需使用具有自引用外键的单个表格:

CREATE TABLE table1 (
  id     NUMBER
         CONSTRAINT table1__id__pk PRIMARY KEY,
  name   VARCHAR2(50),
  parent CONSTRAINT table1__parent__fk REFERENCES table1 (id)
);

然后您可以使用:

SELECT t.*,
       LEVEL,
       CONNECT_BY_ISLEAF,
       SYS_CONNECT_BY_PATH(name, '>') AS ancestors
FROM   table1 t
START WITH parent IS NULL
CONNECT BY PRIOR id = parent
ORDER SIBLINGS BY name;

对于样本数据:

INSERT INTO table1 (id, name, parent)
SELECT 1, 'Alice', NULL FROM DUAL UNION ALL
SELECT 2, 'Beryl', 1 FROM DUAL UNION ALL
SELECT 3, 'Carol', 1 FROM DUAL UNION ALL
SELECT 4, 'Debra', 2 FROM DUAL UNION ALL
SELECT 5, 'Emily', 3 FROM DUAL UNION ALL
SELECT 6, 'Fiona', 4 FROM DUAL;

输出:

ID NAME PARENT LEVEL CONNECT_BY_ISLEAF ANCESTORS
1 Alice null 1 0 > Alice
2 Beryl 1 2 0 > Alice > Beryl
4 Debra 2 3 0 > Alice > Beryl > Debra
6 Fiona 4 4 1 > Alice > Beryl > Debra > Fiona
3 Carol 1 2 0 > Alice > Carol
5 Emily 3 3 1 > Alice > Carol > Emily

fiddle


更新

> 想象Table1代表一个州,Table2代表一个城市,Table3代表一个邮政编码 - 这些都有它们自己独特的属性,一个州有很多城市,一个城市有很多邮政编码。

如果您有三个不同的数据集(州、城市和邮政编码),每个数据集都有其独特的属性,那么请使用三个不同的表格。

CREATE TABLE state (
  id                    NUMBER PRIMARY KEY,
  name                  VARCHAR2(50),
  government            VARCHAR2(50),
  flag                  BLOB
);

CREATE TABLE city (
  id                    NUMBER PRIMARY KEY,
  state_id              REFERENCES state (id),
  mayor                 VARCHAR2(20),
  rat_population        NUMBER(4,0)
);

CREATE TABLE zip_code (
  id                    NUMBER PRIMARY KEY,
  state_id              REFERENCES state (id),
  nearest_city_id       REFERENCES city (id),
  refuse_collection_day VARCHAR2(9)
);

如果您想要查找关于表的信息,只需在想要组合两个或更多数据集时使用引用约束上的 JOIN。对于这种类型的数据,不要使用分层查询。

英文:

Just use a single table with a self-referential foreign key:

CREATE TABLE table1 (
  id     NUMBER
         CONSTRAINT table1__id__pk PRIMARY KEY,
  name   VARCHAR2(50),
  parent CONSTRAINT table1__parent__fk REFERENCES table1 (id)
);

Then you can use:

SELECT t.*,
       LEVEL,
       CONNECT_BY_ISLEAF,
       SYS_CONNECT_BY_PATH(name, ' > ') AS ancestors
FROM   table1 t
START WITH parent IS NULL
CONNECT BY PRIOR id = parent
ORDER SIBLINGS BY name;

Which, for the sample data:

INSERT INTO table1 (id, name, parent)
SELECT 1, 'Alice', NULL FROM DUAL UNION ALL
SELECT 2, 'Beryl', 1 FROM DUAL UNION ALL
SELECT 3, 'Carol', 1 FROM DUAL UNION ALL
SELECT 4, 'Debra', 2 FROM DUAL UNION ALL
SELECT 5, 'Emily', 3 FROM DUAL UNION ALL
SELECT 6, 'Fiona', 4 FROM DUAL;

Outputs:

ID NAME PARENT LEVEL CONNECT_BY_ISLEAF ANCESTORS
1 Alice null 1 0  > Alice
2 Beryl 1 2 0  > Alice > Beryl
4 Debra 2 3 0  > Alice > Beryl > Debra
6 Fiona 4 4 1  > Alice > Beryl > Debra > Fiona
3 Carol 1 2 0  > Alice > Carol
5 Emily 3 3 1  > Alice > Carol > Emily

fiddle


Update

> Imagine Table1 represent a State, Table2 represents a City, and Table3 represents a Zip code - these all have their own unique properties, and a State has many Cities, and a City has many Zip Codes.

If you have three distinct sets of data (states, cities and zip codes) each with properties that are unique to that set of data then use three different three tables.

CREATE TABLE state (
  id                    NUMBER PRIMARY KEY,
  name                  VARCHAR2(50),
  government            VARCHAR2(50),
  flag                  BLOB
);

CREATE TABLE city (
  id                    NUMBER PRIMARY KEY,
  state_id              REFERENCES state (id),
  mayor                 VARCHAR2(20),
  rat_population        NUMBER(4,0)
);

CREATE TABLE zip_code (
  id                    NUMBER PRIMARY KEY,
  state_id              REFERENCES state (id),
  nearest_city_id       REFERENCES city (id),
  refuse_collection_day VARCHAR2(9)
);

If you want to find information about the tables then just use a JOIN on the referential constraints when you want to combine two-or-more data sets. You do not want to use a hierarchical query for this type of data.

huangapple
  • 本文由 发表于 2023年2月7日 05:10:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/75366620.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定