oracle sql field from cross reference table - sql

i am novice at SQL and have problems hope you can help me :
ORACLE 10g
table ACCOUNT
+----------+----------+
| ACCOUNTID| LBKEY |
+----------+----------+
| ... | ... |
| 254 | value254 |
| ... | ... |
| 401 | value401 |
| ... | ... |
| 405 | value405 |
+----------+----------+
cross reference table
+----------+----------+----------+--------+
| IDTABLE2 | ACCOUNTID| OIDID | VALUE |
+----------+----------+----------+--------+
| ... | ... | ... | ... |
| 475 | 401 | 4 | 40000 |
| 476 | 405 | 4 | 35000 |
| ...| ... | ... | ... |
| 3000 | 254 | 5 | PARIS |
| 3001 | 401 | 5 | LONDON |
| 3002 | 405 | 5 | SYDNEY |
| ...| ... | ... | ... |
+----------+----------+----------+--------+
table OID
+----------+-------------+-------------+
| OIDID | OID | DESCRIPTION |
+----------+-------------+-------------+
| 1 | x | x |
| 2 | x | x |
| 3 | x | x |
| 4 | 1.3.6.1.4.1 | Post Code |
| 5 | 1.3.6.1.4.2 | City |
| 6 | x | x |
| 7 | x | x |
| 8 | x | x |
| 9 | x | x |
| 10 | x | x |
+----------+-------------+-------------+
Expected result
Constraint : all the ACCOUNT (LBKEY) who has one postal code(OID 4) or city code(OID 5) in the cross reference table
+----------+-------------+-------------+
| LBKEY | POST CODE | CITY |
+----------+-------------+-------------+
| value254 | null | PARIS |
| value401 | 40000 | LONDON |
| value405 | 35000 | SYDNEY |
+----------+-------------+-------------+

Three different ways of doing it:
SQL Fiddle
Oracle 11g R2 Schema Setup:
CREATE TABLE ACCOUNT ( ACCOUNTID, LBKEY ) AS
SELECT 254, 'value254' FROM DUAL
UNION ALL SELECT 401, 'value401' FROM DUAL
UNION ALL SELECT 405, 'value405' FROM DUAL
UNION ALL SELECT 406, 'value406' FROM DUAL;
CREATE TABLE CrossReference ( IDTABLE2, ACCOUNTID, OIDID, VALUE ) AS
SELECT 475, 401, 4, '40000' FROM DUAL
UNION ALL SELECT 476, 405, 4, '35000' FROM DUAL
UNION ALL SELECT 3000, 254, 5, 'PARIS' FROM DUAL
UNION ALL SELECT 3001, 401, 5, 'LONDON' FROM DUAL
UNION ALL SELECT 3002, 405, 5, 'SYDNEY' FROM DUAL
UNION ALL SELECT 4000, 406, 6, 'x' FROM DUAL;
CREATE TABLE OID (OIDID, OID, DESCRIPTION ) AS
SELECT 1, 'x', 'x' FROM DUAL
UNION ALL SELECT 2, 'x', 'x' FROM DUAL
UNION ALL SELECT 3, 'x', 'x' FROM DUAL
UNION ALL SELECT 4, '1.3.6.1.4.1', 'Post Code' FROM DUAL
UNION ALL SELECT 5, '1.3.6.1.4.2', 'City' FROM DUAL
UNION ALL SELECT 6, 'x', 'x' FROM DUAL
UNION ALL SELECT 7, 'x', 'x' FROM DUAL
UNION ALL SELECT 8, 'x', 'x' FROM DUAL
UNION ALL SELECT 9, 'x', 'x' FROM DUAL
UNION ALL SELECT 10, 'x', 'x' FROM DUAL;
Query 1:
SELECT LBKEY,
MAX( CASE OIDID WHEN 4 THEN VALUE END ) AS "Post Code",
MAX( CASE OIDID WHEN 5 THEN VALUE END ) AS "City"
FROM ACCOUNT a
INNER JOIN
CrossReference c
ON ( a.ACCOUNTID = c.ACCOUNTID )
WHERE c.OIDID IN ( 4, 5 )
GROUP BY LBKEY
Results:
| LBKEY | POST CODE | CITY |
|----------|-----------|--------|
| value254 | (null) | PARIS |
| value405 | 35000 | SYDNEY |
| value401 | 40000 | LONDON |
Query 2:
WITH data AS (
SELECT LBKEY,
( SELECT VALUE
FROM CrossReference c
WHERE c.ACCOUNTID = a.ACCOUNTID
AND c.OIDID = 4 ) AS "Post Code",
( SELECT VALUE
FROM CrossReference c
WHERE c.ACCOUNTID = a.ACCOUNTID
AND c.OIDID = 5 ) AS "City"
FROM ACCOUNT a
)
SELECT *
FROM data
WHERE "Post Code" IS NOT NULL
OR "City" IS NOT NULL
Results:
| LBKEY | POST CODE | CITY |
|----------|-----------|--------|
| value254 | (null) | PARIS |
| value401 | 40000 | LONDON |
| value405 | 35000 | SYDNEY |
Query 3:
SELECT LBKEY,
c1.VALUE AS "Post Code",
c2.VALUE AS City
FROM ACCOUNT a
LEFT OUTER JOIN
( SELECT ACCOUNTID, VALUE FROM CrossReference WHERE OIDID = 4 ) c1
ON ( c1.ACCOUNTID = a.ACCOUNTID )
LEFT OUTER JOIN
( SELECT ACCOUNTID, VALUE FROM CrossReference WHERE OIDID = 5 ) c2
ON ( c2.ACCOUNTID = a.ACCOUNTID )
WHERE c1.VALUE IS NOT NULL
OR c2.VALUE IS NOT NULL
Results:
| LBKEY | POST CODE | CITY |
|----------|-----------|--------|
| value254 | (null) | PARIS |
| value401 | 40000 | LONDON |
| value405 | 35000 | SYDNEY |

I think this could work for you:
select
lbkey,
cross_post.value as postcode,
cross_city.value as city
from
ACCOUNT a,
cross cross_city,
cross cross_post,
where
a.accountid=cross_city.accountid(+) and
a.accountid=cross_post.accountid(+) and
nvl(cross_city.oidid,5)=5 and
nvl(cross_post.oidid,4)=4 and
(cross_city.oidid is not null or cross_post.oidid is not null)

Related

make recent log agg with unix timestamp in BigQuery

I'm making a webpage user access log table in BigQuery.
But I don't know how agg log with exit_time.
I want recent 5 view page log array.
If view page log is less than 5, the array is shorter.
plz teach me.
USER_EXIT_LOG AS (
SELECT
['A','A','B'] AS user_id,
[1000,2000,1000] AS exit_time
),
VIEW_PAGE_LOG AS (
SELECT
['A','A','A','A','A','B','B'] AS user_id,
['a','b','c','d','e','a','b'] AS view_page_id,
[800,900,1800,1900,1950,800,900] AS time
)
USER_EXIT_LOG
| user_id | exit_time |
| -------- | --------- |
| A | 1000 |
| A | 2000 |
| B | 1000 |
VIEW_PAGE_LOG
| user_id | view_page_id | view_time |
| -------- | ----------- | --------- |
| A | a | 800 |
| A | b | 900 |
| A | c | 1800 |
| A | d | 1900 |
| B | a | 800 |
| B | b | 900 |
WHAT I WANT
| user_id | exit_time | view_page_array |
| ------- | --------- | --------------- |
| A | 1000 | [b,a] |
| A | 2000 | [e,d,c] |
| B | 1000 | [b,a] |
Consider below
select u.user_id, exit_time,
array_agg(view_page_id order by view_time desc limit 5) as view_page_array
from (
select user_id, exit_time,
ifnull(lag(exit_time + 1) over(partition by user_id order by exit_time), 0) start_time
from `project.dataset.USER_EXIT_LOG`
) u
join `project.dataset.VIEW_PAGE_LOG` v
on u.user_id = v.user_id
and view_time between start_time and exit_time
group by user_id, exit_time
If applied t sample data in your question
with `project.dataset.USER_EXIT_LOG` as (
select 'A' user_id, 1000 exit_time union all
select 'A', 2000 union all
select 'B', 1000
), `project.dataset.VIEW_PAGE_LOG` as (
select 'A' user_id, 'a' view_page_id, 800 view_time union all
select 'A', 'b', 900 union all
select 'A', 'c', 1800 union all
select 'A', 'd', 1900 union all
select 'A', 'e', 1950 union all
select 'B', 'a', 800 union all
select 'B', 'b', 900
)
the output is

Query to fetch distinct rows with below requirement

Sample date in the table:
+--------+---------+---------+--------------+-----------+------------+---+
| School | Class | Student | Student desc | Section | Date | |
+--------+---------+---------+--------------+-----------+------------+---+
| ABC | Grade 2 | Stud 1 | AAA | Mango | 5/12/2015 | 1 |
| DEF | Grade 2 | Stud 1 | AAA | Mango | 12/25/2018 | |
| DEF | Grade 2 | Stud 1 | AAA | Orange | 9/8/2016 | |
| GHI | Grade 3 | Stud 2 | BBB | Apple | 12/28/2016 | 2 |
| JKL | Grade 3 | Stud 2 | BBB | Pear | 12/19/2016 | |
| ABC | Grade 2 | Stud 3 | CCC | Guava | 12/28/2016 | 3 |
| GHI | Grade 3 | Stud 4 | DDD | StarFruit | 9/8/2018 | 4 |
+--------+---------+---------+--------------+-----------+------------+---+
Ideally mapping should be 1 student is only get assigned to one section in a class.
I need to build the query to fetch the data to meet below requirement:-
Irrespective of the School need to show the distinct data for those students which get assigned to multiple sections within same class.
+--------+---------+---------+--------------+----------+------------+
| School | Class | Student | Student desc | Section | Date |
+--------+---------+---------+--------------+----------+------------+
| DEF | Grade 2 | Stud 1 | AAA | Mango | 12/25/2018 |
| DEF | Grade 2 | Stud 1 | AAA | Orange | 9/8/2016 |
| GHI | Grade 3 | Stud 2 | BBB | Apple | 12/28/2016 |
| JKL | Grade 3 | Stud 2 | BBB | Pear | 12/19/2016 |
+--------+---------+---------+--------------+----------+------------+
Below is the query that provides the correct data if school information is fetched:
select distinct a.class
,a.student
,a.Stud desc
,a.section
,to_date(max(a.date),'MM-DD-YYYY')"Date"
from Table1 a,
( select class
,student
,count(distinct section) cot
from Table1 c
where 1=1
and class is not null
and incoming_qty >= 1
group by class
,student
Having count(distinct section) > 1
) b
where 1=1
and a.class = b.class
and a.student=b.student
and b.cot > 1
and b.class is not null
and a.incoming_qty_new >= 1
group by a.class,a.student,a.Stud desc,a.section
order by a.class,a.student,a.Stud desc,a.section;
But query not working as per expectation while trying to fetch the school detail.
Please suggest.
Here is example of analytic functions usage for your data. Try to extend it for your specific case.
WITH t(School, Class, Student, StudentDesc, SectionName, Dates) AS
(
SELECT 'ABC','Grade 2','Stud 1','AAA','Mango',date'2015-05-12' FROM dual UNION ALL
SELECT 'DEF','Grade 2','Stud 1','AAA','Mango',date'2018-12-25' FROM dual UNION ALL
SELECT 'DEF','Grade 2','Stud 1','AAA','Orange',date'2016-09-08' FROM dual UNION ALL
SELECT 'GHI','Grade 3','Stud 2','BBB','Apple',date'2016-12-28' FROM dual UNION ALL
SELECT 'JKL','Grade 3','Stud 2','BBB','Pear',date'2016-12-19' FROM dual UNION ALL
SELECT 'ABC','Grade 2','Stud 3','CCC','Guava',date'2016-12-28' FROM dual UNION ALL
SELECT 'GHI','Grade 3','Stud 4','DDD','StarFruit',date'2018-09-08' FROM dual
)
SELECT *
FROM (
SELECT t.*,
COUNT(DISTINCT SectionName) OVER (PARTITION BY Class, Student) AS cntStudentSections,
ROW_NUMBER() OVER (PARTITION BY Class, Student ORDER BY Dates) AS StudentRowNumber
FROM t
)
WHERE cntStudentSections > 1 AND StudentRowNumber = 1;
You can use analytic functions:
select t1.*
from (select t1.*,
count(*) over (partition by class, student, section) as cnt
from table1 t1
) t1
where cnt >= 2;

Hierarchical table in Oracle

I have a problem with creating Hierarchical table, I searched a lot but this problem maybe different from the popular problem.
I have table that need to reconstruct
The input table :
| Agency_CODE | Code_length | Agency_Name
| 1 | 1 | Boogy
| 11 | 2 | Elhady
| 12 | 2 | EzzBatriq
| 13 | 2 | Haythomy
| 111 | 3 | Migz
| 121 | 3 | Mido
| 131 | 3 | Thabet
The hierarchy should be as : The agency which has only one digit is the root of the hierarchy 'Level 1', and level 2 the items which has two digits and level 3 which has 3 digits. Here we have 3 levels
So we need a query to get this output:
|Parent_ID |Parent_Name|Child_1_Id|Child_1_name|Child_2_Id|Child_2_name|
| 1 | Boogy | 11 | Elhady | 111 | Migz |
| 1 | Boogy | 12 | EzzBatriq | 121 | Mido |
| 1 | Boogy | 13 | Haythomy | 131 | Thabet |
Thanks in advance
SQL Fiddle
Oracle 11g R2 Schema Setup:
CREATE TABLE Agencies (
Agency_CODE NUMBER(8,0) CONSTRAINT Agencies__AC__PK PRIMARY KEY,
Code_length NUMBER(4,0) GENERATED ALWAYS AS ( LENGTH( Agency_Code ) ) VIRTUAL,
Agency_Name VARCHAR2(50),
parent_code NUMBER(7,0) GENERATED ALWAYS AS ( SUBSTR( Agency_Code, 1, LENGTH( Agency_Code ) - 1 ) ) VIRTUAL
CONSTRAINT Agencies__PC__FK REFERENCES Agencies( Agency_Code )
);
INSERT INTO Agencies ( Agency_CODE, Agency_Name )
SELECT 1, 'Boogy' FROM DUAL UNION ALL
SELECT 11, 'Elhady' FROM DUAL UNION ALL
SELECT 12, 'EzzBatriq' FROM DUAL UNION ALL
SELECT 13, 'Haythomy' FROM DUAL UNION ALL
SELECT 111, 'Migz' FROM DUAL UNION ALL
SELECT 121, 'Mido' FROM DUAL UNION ALL
SELECT 131, 'Thabet' FROM DUAL;
Query 1:
SELECT CONNECT_BY_ROOT( Agency_Code ) AS parent_id,
CONNECT_BY_ROOT( Agency_name ) AS parent,
PRIOR( Agency_Code ) AS child_id,
PRIOR( Agency_name ) AS child,
Agency_Code AS child2_id,
Agency_Name AS child2
FROM Agencies
WHERE LEVEL = 3
START WITH Code_length = 1
CONNECT BY PRIOR Agency_code = parent_code
Results:
| PARENT_ID | PARENT | CHILD_ID | CHILD | CHILD2_ID | CHILD2 |
|-----------|--------|----------|-----------|-----------|--------|
| 1 | Boogy | 11 | Elhady | 111 | Migz |
| 1 | Boogy | 12 | EzzBatriq | 121 | Mido |
| 1 | Boogy | 13 | Haythomy | 131 | Thabet |
Update: If you know the maximum depth of your nested hierarchy then you can use PIVOT:
SQL Fiddle
Oracle 11g R2 Schema Setup:
INSERT INTO Agencies ( Agency_CODE, Agency_Name )
SELECT 1311, 'Thabet.1' FROM DUAL;
Query 2:
SELECT *
FROM (
SELECT CONNECT_BY_ROOT( Agency_Code ) AS leaf_id,
Agency_Code,
code_length,
Agency_Name
FROM Agencies a
START WITH NOT EXISTS (
SELECT 1
FROM Agencies x
WHERE x.parent_code = a.agency_code
)
CONNECT BY PRIOR parent_code = Agency_code
) a
PIVOT(
MAX( agency_code ) AS id,
MAX( agency_name ) AS name
FOR code_length IN (
1 AS parent,
2 AS child,
3 AS child1,
4 AS child2
)
)
Results:
| LEAF_ID | PARENT_ID | PARENT_NAME | CHILD_ID | CHILD_NAME | CHILD1_ID | CHILD1_NAME | CHILD2_ID | CHILD2_NAME |
|---------|-----------|-------------|----------|------------|-----------|-------------|-----------|-------------|
| 121 | 1 | Boogy | 12 | EzzBatriq | 121 | Mido | (null) | (null) |
| 1311 | 1 | Boogy | 13 | Haythomy | 131 | Thabet | 1311 | Thabet.1 |
| 111 | 1 | Boogy | 11 | Elhady | 111 | Migz | (null) | (null) |

Output records that match the condition, as well as their parent records up to the root record. Oracle SQL

There is such an Oracle table:
+----+-----+--------+
| ID | PID | NAME |
+----+-----+--------+
| 1 | | testX |
| 2 | | test2 |
| 3 | 2 | test3 |
| 4 | 3 | testX |
| 5 | 3 | test5 |
| 6 | 3 | test6 |
| 7 | 4 | test7 |
| 8 | 5 | test8 |
| 9 | 3 | test9 |
| 10 | 4 | test10 |
| 11 | 5 | testX |
| 12 | 5 | test12 |
+----+-----+--------+
, where pid is the id of the parent record.
Need to output all records that match the condition, as well as their parent records up to the root record.
Such parent records should not be duplicated with those parent records that are found during the search phase.
For example, under this condition where name = 'testX', should get this result:
+----+-----+-------+
| ID | PID | NAME |
+----+-----+-------+
| 1 | | testX |
| 2 | | test2 |
| 3 | 2 | test3 |
| 4 | 3 | testX |
| 5 | 3 | test5 |
| 11 | 5 | testX |
+----+-----+-------+
How to do it?
P.S. Oracle 11.2.0.4.0.
I'm sure there is a more elegant way to do this, but this is what I came up with.
This is the with clause to generate the sample data:
with testdata as
(select 1 ID, null PID, 'testX' NAME from dual union all
select 2 , null, 'test2' from dual union all
select 3 , 2, 'test3' from dual union all
select 4 , 3, 'testX' from dual union all
select 5 , 3, 'test5' from dual union all
select 6 , 3, 'test6' from dual union all
select 7 , 4, 'test7' from dual union all
select 8 , 5, 'test8' from dual union all
select 9 , 3, 'test9' from dual union all
select 10, 4, 'test10' from dual union all
select 11, 5, 'testX' from dual union all
select 12, 5, 'test12' from dual)
Here is the query:
select distinct id, pid, name
from(
select sys_connect_by_path(name,'/') path,
id, pid, name
from testdata
connect by prior PID = ID)
where instr(path,'/testX') > 0
order by id
I used SYS_CONNECT_BY_PATH in order to get the name field from all parents. Then I just checked that testX was one of the elements in the string using instr.
My results are:
ID PID NAME
1 testX
2 test2
3 2 test3
4 3 testX
5 3 test5
11 5 testX
This simple query should help -
SELECT distinct id, pid, name FROM tab1
connect by prior pid = id
start with name = 'testX'
order by id
;
http://sqlfiddle.com/#!4/8da121/6/0
Output -
ID PID NAME
1 (null) testX
2 (null) test2
3 2 test3
4 3 testX
5 3 test5
11 5 testX

sql query oracle to fit a tree structure format

I have created these sample tables to create a json tree structure so that i can use jqtree to create a tree layout.
I want my json to be in the format
[
{"id":1, "parentid": 0, "name": "Carnivores"},
{"id":2, "parentid": 0, "name": "Herbivores"},
{"id":3, "parentid": 1, "name": "Dogs"},
{"id":4, "parentid": 3, "name": "Labradors"},
{"id":5, "parentid": 3, "name": "Pugs"},
{"id":6, "parentid": 3, "name": "Terriers"}
]
The tables are as follows.
| catg_id | catg_name |
| —————- |————————- |
| 1 | Carnivores |
| 2 | Herbivores |
| animal_catg_id | animal_catg_name | catg_id |
| —————- |————————- |————————- |
| 1 | Dogs | 1 |
| 2 | Cats | 1 |
| 3 | Cows | 2 |
| 4 | Buffalo | 2 |
| animal_id | animal_name | animal_catg_id |
| —————- |————————- | ————————- |
| 1 | labs | 1 |
| 2 | pugs | 1 |
| 3 | terriers | 1 |
| 4 | german | 1 |
| 5 | lion | 2 |
| 6 | tiger | 2 |
I am assuming it would be hierarchical query, i have never written one before, i need some help with that.
I don't know where to start and how to start it.
EDIT
One of the comments in the answers is that the schema design is not clear.
What changes should I do to make to get the data in the json format, so that it maintains the hierarchy
EDIT2
My current query returns this table
Carnivores | Dogs | labs
Carnivores | Dogs | pugs
Carnivores | Dogs | terriers
.......
The JSON you are proposing appears to have no correlation between the IDs you are assigning and the IDs in the tables this will make it difficult to connect anything from the client-side back to the database.
You would be better re-organising your tables so that you can put everything into a single hierarchical structure. Something like a Linnaean Taxonomy:
SQL Fiddle
Oracle 11g R2 Schema Setup:
CREATE TABLE Taxonomies ( ID, PARENT_ID, Category, Taxonomy, Common_Name ) AS
SELECT 1, CAST(NULL AS NUMBER), 'Kingdom', 'Animalia', 'Animal' FROM DUAL
UNION ALL SELECT 2, 1, 'Phylum', 'Chordata', 'Chordate' FROM DUAL
UNION ALL SELECT 3, 2, 'Class', 'Mammalia', 'Mammal' FROM DUAL
UNION ALL SELECT 4, 3, 'Order', 'Carnivora', 'Carnivore' FROM DUAL
UNION ALL SELECT 5, 4, 'Family', 'Felidae', 'Feline' FROM DUAL
UNION ALL SELECT 6, 5, 'Genus', 'Panthera', 'Tiger' FROM DUAL
UNION ALL SELECT 7, 5, 'Genus', 'Felis', 'Cat' FROM DUAL
UNION ALL SELECT 8, 5, 'Genus', 'Lynx', 'Lynx' FROM DUAL
UNION ALL SELECT 9, 4, 'Family', 'Canidae', 'Canid' FROM DUAL
UNION ALL SELECT 10, 9, 'Genus', 'Canis', 'Canine' FROM DUAL
UNION ALL SELECT 11, 10, 'Species', 'Canis Lupus', 'Gray Wolf' FROM DUAL
UNION ALL SELECT 12, 11, 'Sub-Species', 'Canis Lupus Familiaris', 'Domestic Dog' FROM DUAL
UNION ALL SELECT 13, 12, 'Breed', NULL, 'Pug' FROM DUAL
UNION ALL SELECT 14, 12, 'Breed', NULL, 'German Shepherd' FROM DUAL
UNION ALL SELECT 15, 12, 'Breed', NULL, 'Labradors' FROM DUAL
UNION ALL SELECT 16, 7, 'Species', 'Felis Catus', 'Domestic Cat' FROM DUAL
UNION ALL SELECT 17, 8, 'Species', 'Lynx Lynx', 'Eurasian Lynx' FROM DUAL
UNION ALL SELECT 18, 8, 'Species', 'Lynx Rufus', 'Bobcat' FROM DUAL;
Then you can extract the data relatively simply:
Query 1 - Get everything taxonomically related to "Cat":
SELECT *
FROM (
SELECT *
FROM Taxonomies
START WITH Common_Name = 'Cat'
CONNECT BY PRIOR PARENT_ID = ID
ORDER BY LEVEL DESC
)
UNION
SELECT *
FROM (
SELECT *
FROM Taxonomies
START WITH Common_Name = 'Cat'
CONNECT BY PRIOR ID = PARENT_ID
ORDER SIBLINGS BY Common_Name
)
Results:
| ID | PARENT_ID | CATEGORY | TAXONOMY | COMMON_NAME |
|----|-----------|----------|-------------|--------------|
| 1 | (null) | Kingdom | Animalia | Animal |
| 2 | 1 | Phylum | Chordata | Chordate |
| 3 | 2 | Class | Mammalia | Mammal |
| 4 | 3 | Order | Carnivora | Carnivore |
| 5 | 4 | Family | Felidae | Feline |
| 7 | 5 | Genus | Felis | Cat |
| 16 | 7 | Species | Felis Catus | Domestic Cat |
Query 2 - Get everything taxonomically related to "Canine":
SELECT *
FROM (
SELECT *
FROM Taxonomies
START WITH Common_Name = 'Canine'
CONNECT BY PRIOR PARENT_ID = ID
ORDER BY LEVEL DESC
)
UNION
SELECT *
FROM (
SELECT *
FROM Taxonomies
START WITH Common_Name = 'Canine'
CONNECT BY PRIOR ID = PARENT_ID
ORDER SIBLINGS BY Common_Name
)
Results:
| ID | PARENT_ID | CATEGORY | TAXONOMY | COMMON_NAME |
|----|-----------|-------------|------------------------|-----------------|
| 1 | (null) | Kingdom | Animalia | Animal |
| 2 | 1 | Phylum | Chordata | Chordate |
| 3 | 2 | Class | Mammalia | Mammal |
| 4 | 3 | Order | Carnivora | Carnivore |
| 9 | 4 | Family | Canidae | Canid |
| 10 | 9 | Genus | Canis | Canine |
| 11 | 10 | Species | Canis Lupus | Gray Wolf |
| 12 | 11 | Sub-Species | Canis Lupus Familiaris | Domestic Dog |
| 13 | 12 | Breed | (null) | Pug |
| 14 | 12 | Breed | (null) | German Shepherd |
| 15 | 12 | Breed | (null) | Labradors |
Here's an example of a hierarchical query from the Oracle documentation:
SELECT last_name, employee_id, manager_id, LEVEL
FROM employees
START WITH employee_id = 100
CONNECT BY PRIOR employee_id = manager_id
ORDER SIBLINGS BY last_name;
http://docs.oracle.com/cd/B19306_01/server.102/b14200/queries003.htm
Something like this in your case but your schema design isn't clear
SELECT animal_name, level
FROM animals
START WITH parentid is null
CONNECT BY PRIOR id = parentid;