0

My table

id name num
1  a    3
2  b    4

I need to return every row num number of times. I do it this way.

  select DB.BAN_KEY as BAN_KEY, DB.CUST_FULLNAME as CUST_FULLNAME
  from TST_DIM_BAN_SELECTED DB
  inner join (select rownum rn from dual connect by level < 10) a
  on a.rn <= DB.N

There resulting table looks like this.

id  name
1   a
1   a
1   a
2   b
2   b
2   b
2   b

But I also need every row in the group to be numbered like this.

id  name row_num
1   a    1
1   a    2
1   a    3
2   b    1
2   b    2
2   b    3
2   b    4

How can I do it?

gjin
  • 860
  • 1
  • 14
  • 28

4 Answers4

1

You can use analytic function for this:

Select id, name, 
row_number() over (partition by id, name order by id, name)
From(/* your query */) t;

This can be done without subquery:

Select id, name, 
row_number() over (partition by id, name order by id, name)
From /* joins */
Gurwinder Singh
  • 38,557
  • 6
  • 51
  • 76
1

You don't need an inner join to a dummy table or an analytic function to generate the row numbers; you could just use connect by (and its corresponding level function) on the table itself, like so:

WITH tst_dim_ban_selected AS (SELECT 1 ban_key, 'a' cust_fullname, 3 n FROM dual UNION ALL
                              SELECT 2 ban_key, 'b' cust_fullname, 4 n FROM dual)
-- end of mimicking your table with data in it. See SQL below
SELECT db.ban_key,
       db.cust_fullname,
       LEVEL row_num
FROM   tst_dim_ban_selected db
CONNECT BY LEVEL <= db.n
           AND PRIOR db.ban_key = db.ban_key -- assuming this is the primary key
           AND PRIOR sys_guid() IS NOT NULL;

   BAN_KEY CUST_FULLNAME    ROW_NUM
---------- ------------- ----------
         1 a                      1
         1 a                      2
         1 a                      3
         2 b                      1
         2 b                      2
         2 b                      3
         2 b                      4

If you have other columns than ban_key in the table's primary key, you need to make sure they are included in the connect by clause's list of prior <column> = <column>s. This is so the connect by can identify each row uniquely, meaning that it's looping just over that row and no others. The PRIOR sys_guid() IS NOT NULL is required to prevent connect by loops from occurring.

Boneist
  • 22,910
  • 1
  • 25
  • 40
0

You could use this:

SELECT db.ban_key AS ban_key, db.cust_fullname AS cust_fullname,
    ROW_NUMBER() OVER (PARTITION BY db.n ORDER BY db.ban_key) AS row_num
FROM tst_dim_ban_selected db
INNER JOIN (SELECT rownum rn FROM dual CONNECT BY level < 10) a
ON a.rn <= db.n;
Pham X. Bach
  • 5,284
  • 4
  • 28
  • 42
0

Use a recursive sub-query factoring clause:

WITH split ( id, name, rn, n ) AS (
  SELECT BAN_KEY, CUST_FULLNAME, 1, N
  FROM   TST_DIM_BAN_SELECTED
UNION ALL
  SELECT id, name, rn + 1, n
  FROM   split
  WHERE  rn < n
)
SELECT id, name, rn
FROM   split;
MT0
  • 143,790
  • 11
  • 59
  • 117