0

I’m encountering some issues with hierarchical structure query in Oracle. Specifically, I’m trying to build a query to represent a hierarchical structure, but the results are not as expected. Here are the details: I created a table in my Oracle database as:

CREATE TABLE EMP ( DNO NUMBER, ENAME VARCHAR2(10), SAL NUMBER );

INSERT INTO EMP (DNO, ENAME, SAL) VALUES (101, 'John', 3000), (101, 'Michael', 2500), (101, 'Scott', 4000), (102, 'Smith', 1500), (102, 'Williams', 2000), (102, 'James', 3500), (103, 'Andrew', 1000), (103, 'Becker', 4500);

When I inserted the above data, my EMP table looked like this:

DNO ENAME SAL
101 John 3000
101 Michael 2500
101 Scott 4000
102 Smith 1500
102 Williams 2000
102 James 3500
103 Andrew 1000
103 Becker 4500

I want my output to be displayed in a hierarchical structure where the DNO is shown only once, followed by its ENAME and SAL. My expected output is as follows:

DNO ENAME SAL
101 John 3000
Michael 2500
Scott 4000
102 Smith 1500
Williams 2000
James 3500
103 Andrew 1000
Becker 4500

I tried several ways, but they didn't work. Can someone help me? Thanks in advance.

2 Answers 2

0

Your data is not really hierarchical, because there are no column(s) which provide for the perceived ordering you think is there. Your actual requirement is to sort by DNO group, and to then display the DNO value only once, for the "first" entry. We can approximate what you want using ROW_NUMBER():

WITH cte AS (
    SELECT e.*, ROW_NUMBER() OVER (PARTITION BY DNO ORDER BY DBMS_RANDOM.VALUE) rn
    FROM EMP e
)

SELECT CASE WHEN rn = 1 THEN DNO END AS DNO, ENAME, SAL
FROM cte t
ORDER BY t.DNO, rn;

Demo

If you have some logic by which we know which employee to report first for a given block of DNO, then you should add these details (and columns) to the question.

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks, Tim, for your immediate response. The output order is not correct; it initially shows NULL values for DNO followed by the corresponding ENAME and SAL values from the second row in the DNO group, then returns with the first row of DNO values along with the corresponding ENAME and SAL values. I expect all the DNO values to be displayed as a group, followed by the corresponding ENAME and SAL. I am getting the same result even when I don’t use DBMS_RANDOM.VALUE.
@Rupa Sorry, had a slight typo in the ORDER BY logic. Check the demo link where it is working as you expect.
Thanks, Tim. It worked out well and met my requirements.
@Rupa Thanks and welcome to Stack Overflow. If this answer resolved your problem, then please consider accepting it, by clicking the green checkmark to the left.
0

If you are using SQL*Plus (or another client application that supports SQL*Plus commands) then you can use BREAK:

BREAK ON dno
  
SELECT * FROM emp ORDER BY dno, ename;

If you are not using a client application that supports BREAK then you can use the ROW_NUMBER analytic function to number the rows and then a CASE expression and TO_CHAR to format the number as a string or a space character for later rows in each group:

SELECT CASE rn
       WHEN 1
       THEN TO_CHAR(dno)
       ELSE ' '
       END AS dno,
       ename,
       sal
FROM   (
         SELECT dno,
                ename,
                sal,
                ROW_NUMBER() OVER (PARTITION BY dno ORDER BY ename) AS rn
         FROM   emp
       ) e
ORDER BY
       e.dno,
       e.ename

Which outputs:

DNO ENAME SAL
101 John 3000
Michael 2500
Scott 4000
102 James 3500
Smith 1500
Williams 2000
103 Andrew 1000
Becker 4500

fiddle

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.