Oracle: Wie frage ich eine hierarchische Tabelle ab?

10

Hintergrund

Dies dient zum Erstellen einiger Ansichten, die wir für die Berichterstellung verwenden.

Ich habe eine Tabelle mit Standorten, wobei die Schlüsselfelder "Standort" und "Eltern" sind .

Die Struktur, die diese beiden Felder auf Ebenenebene erstellen, entspricht dem Firmennamen -> Campusname -> Gebäudename -> Etagenname -> Raumname. Der Firmenname bleibt derselbe und der Name des Campus bleibt in diesem Fall derselbe.

Die Struktur der Standorte sieht im Allgemeinen folgendermaßen aus:

                                 +-----------+
                                 | Org. Name |
                                 +-----+-----+
                                       |
                                 +-----v-----+
           +--------------------+|Campus Name|+---+--+-------------+
           |                     +--+--------+    |                |
           |                        |             |                |
           |                        |             |                |
        +--+-----+           +------+-+        +--+----+       +---+---+
    +--+| BLDG-01|+--+       | BLDG-02|        |BLDG-03|       |Grounds|
    |   +--------+   |       +--------+        +-------+       +-------+
  +-+------+   +-----+--+
  |Floor-01|   |Basement+-------+
  +-+------+   +--------+       |
    |                           |
    |                           |
    | +----------+      +-------+--+
    +-+Room 1-001|      |Room B-002|
      +----------+      +----------+

Jeder Standort ist mit dem übergeordneten Standort verknüpft, der letztendlich der Name der Organisation ist. Derzeit gibt es nur eine Organisation und einen Campus.

Tore

  • Ich möchte in der Lage sein, alle Standorte unter einem bestimmten Standort auf der Ebene "Gebäude" abzufragen. Auf diese Weise kann ich beispielsweise zurückgeben, wie viele Arbeitsaufträge für einen Standort innerhalb eines bestimmten Gebäudes ausgeführt wurden.
  • Ich möchte feststellen können, welcher Unterort zu welchem ​​Gebäude gehört . Im Wesentlichen das Gegenteil; Ich möchte von jeder Ebene unterhalb der Gebäudeebene zurückgehen und zurückverfolgen, was das Gebäude ist.
  • Ich möchte, dass dies in einer Ansicht ist . Das heißt, ich hätte gerne eine Tabelle, in der für jedes Element auf der Ebene "Gebäude" das Gebäude in der linken Spalte und alle möglichen Standorte UNTER diesem Gebäude in der rechten Spalte aufgeführt sind. Auf diese Weise hätte ich eine Liste, die ich jederzeit abfragen könnte, um herauszufinden, welche Standorte zu welchem ​​Gebäude gehören.

Versuche und es richtig machen

Ich habe versucht, dies durch schrecklich konstruierte Ansichten, UNION-Abfragen usw. zu tun - was alles eine schlechte Idee zu sein schien. Ich weiß, dass Oracle durch "CONNECT BY" einen Mechanismus dafür besitzt. Ich bin mir nur nicht sicher, wie ich davon Gebrauch machen soll.

SeanKilleen
quelle
Wie werden "Wurzel" -Knoten identifiziert? Ist Eltern NULLfür sie? Wie identifizieren Sie eine "Gebäudeebene"?
a_horse_with_no_name
@a_horse_with_no_name logischerweise würde die Ebene "Gebäude" alles mit einem Elternteil sein, das der Campusname ist, dh alles mit einem Elternteil von "MAINCAMPUS". Die Wurzel aller Knoten ist "COMPANYNAME", das übergeordnete Element von "MAINCAMPUS", und alle Gebäude (plus "Gelände") haben MAINCAMPUS als übergeordnetes Element.
SeanKilleen
Beeindruckend! Wie hast du das geschaffen !! Google für "Adjacency Model in SQL" Sie werden alle eingestellt
srini.venigalla
PS: Für diejenigen, die daran interessiert waren, wie ich das Diagramm erstellt habe, habe ich eine kleine Website namens asciiflow.com verwendet - ich bin ein großer Fan für solche Situationen.
SeanKilleen

Antworten:

4

FrusteratedWithFormsDesigner hat die richtige Richtung (+1). Hier ist, was ich denke, dass Sie speziell suchen.

CREATE OR REPLACE VIEW BuildingSubs AS
   SELECT connect_by_root location "Building", location "SubLocation"
   FROM some_table l
   START WITH l.Location IN 
      (
         SELECT location FROM
         (
         SELECT level MyLevel, location FROM some_table 
         START WITH parent IS NULL 
         CONNECT BY PRIOR location=parent
         )
         WHERE MyLevel=3   
      )
   CONNECT BY PRIOR l.location = l.parent;

select * from BuildingSubs; 

Building             SubLocation        
-------------------- --------------------
BLDG-01              BLDG-01              
BLDG-01              Basement             
BLDG-01              Room B-002           
BLDG-01              Floor-01             
BLDG-01              Room 1-001           
BLDG-02              BLDG-02              
BLDG-03              BLDG-03              
Grounds              Grounds              

Die Ansicht erreicht alle drei Ziele. Sie können es nach einem Gebäude abfragen, um alles zu finden, was es enthält, und Sie können es nach einem Unterort abfragen, um herauszufinden, in welchem ​​Gebäude es sich befindet.

drop table some_table;
create table some_table (Location Varchar2(20), Parent Varchar2(20));

insert into some_table values ('Org. Name',NULL);
insert into some_table values ('MAINCAMPUS','Org. Name');
insert into some_table values ('BLDG-01','MAINCAMPUS');
insert into some_table values ('BLDG-02','MAINCAMPUS');
insert into some_table values ('BLDG-03','MAINCAMPUS');
insert into some_table values ('Grounds','MAINCAMPUS');
insert into some_table values ('Floor-01','BLDG-01');
insert into some_table values ('Basement','BLDG-01');
insert into some_table values ('Room B-002','Basement');
insert into some_table values ('Room 1-001','Floor-01');

Wenn Sie das Gebäude selbst nicht als einen der Unterorte zählen möchten, können Sie die vorhandene Abfrage in einen einschließen, um Einträge zu eliminieren, bei denen das Gebäude und der Unterort identisch sind.

Leigh Riffel
quelle
Leigh, genau das war es. Danke für die Hilfe!
SeanKilleen
9

CONNECT BY ist der richtige Weg, um mit Daten umzugehen, die natürlich rekursiv sind.

Ich weiß nicht, wie dein Tisch aussieht, aber vielleicht so etwas wie:

SELECT *
FROM some_table st
START WITH st.location = 'BLDG-01'
CONNECT BY PRIOR st.location = st.parent;

Dies sollte Knoten unter "BLDG-01" bekommen.

Die START WITHKlausel ist Ihr Basisfall.

Eine andere Erklärung (abgesehen von der Oracle-Erklärung, von der ich annehme, dass Sie sie bereits gelesen haben und mit der Sie Probleme hatten, ist sie wahrscheinlich sehr knapp):

http://www.adp-gmbh.ch/ora/sql/connect_by.html

Ebenfalls:

http://psoug.org/reference/connectby.html

Und:

http://www.oradev.com/connect_by.jsp

FrustratedWithFormsDesigner
quelle
Danke für die Antwort! Ich verstehe genug, um zu erkennen, dass ich meine Frage nicht gut formuliert habe. Meine Tabellenstruktur besteht aus zwei Spalten - "location" und "parent". Die von diesen erstellte Hierarchie wird durch mein ASCII-Diagramm definiert. Ich möchte eine Ansicht erstellen, die für jeden Standort auf der Ebene "Gebäude" alle Standorte unter seinem Zweig anzeigt. Mein Ziel ist es, in der Lage zu sein, ein Gebäude abzufragen und alle seine Unterpositionen abzurufen oder eine Unterposition abzufragen und zu sehen, zu welchem ​​Gebäude es gehört, über eine Ansicht (also kein fest definiertes "Gebäude-x" in der Abfrage). Jede Hilfe wäre sehr dankbar!
SeanKilleen
2

Ich bin mir nicht sicher, ob ich Ihre Frage vollständig verstehe, aber vielleicht so etwas:

select location, 
       parent,
       sys_connect_by_path(location, '/') as item_list,
       case level
         when 1 then 'building'
         when 2 then 'floor'
         when 3 then 'room'
       end as item_type
from some_table 
start with parent = 'MAINCAMPUS'
connect by prior location = parent;

Dies zeigt Ihnen die Hierarchie für jeden Standort

ein Pferd ohne Name
quelle