TIPS(46) : ROWNUM(ORDERING 순으로 NUMBERING, RANGE SELECT)
제품 : SQL*PLUS
작성날짜 : 2003-07-30
TIPS(46) : ROWNUM(ORDERING 순으로 NUMBERING, RANGE SELECT)
=========================================================
PURPOSE
Explanation
SQL*PLUS에서 ORDERING 순으로 NUMBERING하기를 원하는 경우가 많으나,
ORDERING이 되기 전에 RANDOM ACCESS 시
ROWNUM이 ASSIGN되기 때문에, 다음과 같은 결과가 나타날 것이다.
SQL> select ename, rownum from emp;
ENAME ROWNUM
ALLEN 1
JONES 2
BLAKE 3
CLARK 4
KING 5
ADAMS 6
JAMES 7
FORD 8
SQL> select ename, rownum from emp order by ename;
ENAME ROWNUM
ADAMS 6
ALLEN 1
BLAKE 3
CLARK 4
FORD 8
JAMES 7
JONES 2
KING 5
Example
다음의 몇 가지 방법을 이용하여 ORDERING 순으로 NUMBERING을 나타내어 보자.
1) RECORD를 COUNT하는 방법 (DATA가 많은 경우 부적절)
SQL> select A.ename, count(*) position
2 from emp A, emp B
3 where A.ename > B.ename
4 or A.ename = B.ename and A.empno >= B.empno
5 group by A.empno, A.ename
6 order by A.ename, A.empno;
ENAME POSITION
ADAMS 1
ALLEN 2
BLAKE 3
CLARK 4
FORD 5
JAMES 6
JONES 7
KING 8
2) INDEX를 이용하는 방법
SQL> create index sort_ix on emp (ename);
Index created.
SQL> select ename, rownum from emp where ename > ' ';
ENAME ROWNUM
ADAMS 1
ALLEN 2
BLAKE 3
CLARK 4
FORD 5
JAMES 6
JONES 7
KING 8
cf) descending인 경우 아래처럼 hint 사용 바람
select /*+ index_desc(emp ename_ix) */
ename, rownum from emp
where ename > ' ' and rownum < 4;
3) OPTIMIZER를 이용하는 방법
SQL> select rownum, ename
2 from emp , dual
3 where emp.ename = dual.dummy (+);
ROWNUM ENAME
1 ADAMS
2 ALLEN
3 BLAKE
4 CLARK
5 FORD
6 JAMES
7 JONES
8 KING
위에서 언급한 내용에 더해서 rownum을 where 절에 사용함에 있어서는
rownum 1을 포함하는 range(예 : 'where rownum <= 100')에 대해서만
정상적인 조회가 가능하다.
만약 rownum 1을 포함하지 않는 range(예 : 'where rownum between 50 and 100')
에 대한 자료 조회를 원한다면 다음과 같이 in-line view를 이용하는 방법을
사용할 수 있다.
select rn, ename
from ( select rownum rn, ename
from emp)
where rn between 3 and 5 ;
RN ENAME
3 BLAKE
4 CLARK
5 KING
Execution Plan
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 VIEW
2 1 COUNT
3 2 TABLE ACCESS (FULL) OF 'EMP'
* 이 때 in-line view의 rownum에는 반드시 alias를 이용해야 한다.
in-line view에 의해서 선택되어지는 data가 많다면 performance가
떨어질 수 있다.
Reference Documents
-------------------
제품 : SQL*PLUS
작성날짜 : 2003-07-30
TIPS(46) : ROWNUM(ORDERING 순으로 NUMBERING, RANGE SELECT)
=========================================================
PURPOSE
Explanation
SQL*PLUS에서 ORDERING 순으로 NUMBERING하기를 원하는 경우가 많으나,
ORDERING이 되기 전에 RANDOM ACCESS 시
ROWNUM이 ASSIGN되기 때문에, 다음과 같은 결과가 나타날 것이다.
SQL> select ename, rownum from emp;
ENAME ROWNUM
ALLEN 1
JONES 2
BLAKE 3
CLARK 4
KING 5
ADAMS 6
JAMES 7
FORD 8
SQL> select ename, rownum from emp order by ename;
ENAME ROWNUM
ADAMS 6
ALLEN 1
BLAKE 3
CLARK 4
FORD 8
JAMES 7
JONES 2
KING 5
Example
다음의 몇 가지 방법을 이용하여 ORDERING 순으로 NUMBERING을 나타내어 보자.
1) RECORD를 COUNT하는 방법 (DATA가 많은 경우 부적절)
SQL> select A.ename, count(*) position
2 from emp A, emp B
3 where A.ename > B.ename
4 or A.ename = B.ename and A.empno >= B.empno
5 group by A.empno, A.ename
6 order by A.ename, A.empno;
ENAME POSITION
ADAMS 1
ALLEN 2
BLAKE 3
CLARK 4
FORD 5
JAMES 6
JONES 7
KING 8
2) INDEX를 이용하는 방법
SQL> create index sort_ix on emp (ename);
Index created.
SQL> select ename, rownum from emp where ename > ' ';
ENAME ROWNUM
ADAMS 1
ALLEN 2
BLAKE 3
CLARK 4
FORD 5
JAMES 6
JONES 7
KING 8
cf) descending인 경우 아래처럼 hint 사용 바람
select /*+ index_desc(emp ename_ix) */
ename, rownum from emp
where ename > ' ' and rownum < 4;
3) OPTIMIZER를 이용하는 방법
SQL> select rownum, ename
2 from emp , dual
3 where emp.ename = dual.dummy (+);
ROWNUM ENAME
1 ADAMS
2 ALLEN
3 BLAKE
4 CLARK
5 FORD
6 JAMES
7 JONES
8 KING
위에서 언급한 내용에 더해서 rownum을 where 절에 사용함에 있어서는
rownum 1을 포함하는 range(예 : 'where rownum <= 100')에 대해서만
정상적인 조회가 가능하다.
만약 rownum 1을 포함하지 않는 range(예 : 'where rownum between 50 and 100')
에 대한 자료 조회를 원한다면 다음과 같이 in-line view를 이용하는 방법을
사용할 수 있다.
select rn, ename
from ( select rownum rn, ename
from emp)
where rn between 3 and 5 ;
RN ENAME
3 BLAKE
4 CLARK
5 KING
Execution Plan
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 VIEW
2 1 COUNT
3 2 TABLE ACCESS (FULL) OF 'EMP'
* 이 때 in-line view의 rownum에는 반드시 alias를 이용해야 한다.
in-line view에 의해서 선택되어지는 data가 많다면 performance가
떨어질 수 있다.
Reference Documents
-------------------
Similar Messages
-
Produce a range of numbers with select from the gaps of ID column
(1)
Suppose I have a table t which has rows like this:
A B
2 4
6 7
I would like to use select to produce rows with numbers ranging between A column and B column inclusive
for each row, like this:
select ... from t ...
2
3
4
6
7
(2)
Suppose I have ID column which has gaps, I would like to get lowest <N> available numbers between the gaps.
I did research, and I can find the range of the gaps, but I cannot have the numbers listed individually, that is why
I ask question (1). But is there a direct way to get the list instead of going through ranges and the list.
For example, I have ID column which has
2
5
6
7
9
2000000
I would like to get a select query that produces
select ...
3
4
8
10
11
I have a way to get a list from 2 to 2000000 and then minus what we have to get all the
gap numbers, but that is not efficient and could runs out of memory.
PS: Before I post to this group, I did research already on "connect by", with recursive queries.First of all, I would like to thank jeneesh and Frank for helpful and correct reply. However, due to the a bug of this forum,
when I mark jeneesh's reply as correct, I cannot mark Frank's reply as correct anymore. Therefore I would like to formally
state here that I have tested both solutions and they are both correct. jeneesh and Frank use different approach, connect by
and less join ( <=, I do not know what is the proper name for it ).
Secondly I would like to report my small findings: use connect by, you control the level from 1 to the max number, so you
do not need to use order by, and the performance is better (0.37 seconds version 0.92 seconds). And also it performs better
if I use an intermediate view to limit the result sets. One line of code is worth one thousand words, now I am posting two
versions of the code and highlighted the points I mentioned here.
I am sorry that either I do not know how to format the code or I do not have the capability when posting on this forum.
The code listing does not look good, but I hope you get the idea. I have "plain text" and I am not if I can use fixed width font
and preserve space. After I used the spelling checker, it becomes double spaced and I have to manually delete the blank lines.
/* I learned about { code } after the post and edited the original post */
Thanks again to both jeneesh and Frank.
"connect by" version:
SQL> VARIABLE new_id_cnt NUMBER
SQL> EXEC :new_id_cnt := 10;
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.00
SQL> WITH my_table AS
2 (
3 SELECT num
4 FROM prs_elm
5 WHERE 1=1
6 )
7 , my_num AS
8 (
9 SELECT num, ct
10 FROM (
11 SELECT num AS num, LEAD(num) OVER (ORDER BY num) - num - 1 AS ct
12 FROM ( SELECT 0 AS num
13 FROM DUAL
14 UNION ALL
15 SELECT num
16 FROM my_table
17 UNION ALL
18 SELECT ( MAX(num) + :new_id_cnt + 1 ) AS num
19 FROM my_table
20 )
21 )
22 WHERE ct >= 1
23 AND ROWNUM <= :new_id_cnt
24 )
25 SELECT num + level AS available_id
26 FROM my_num
27 WHERE ROWNUM <= :new_id_cnt
28 CONNECT BY level <= ct
29 AND prior num = num
30 AND prior sys_guid() is not null
31 ;
AVAILABLE_ID
3219
3261
3264
3269
3270
3275
3281
3288
3289
3290
10 rows selected.
Elapsed: 00:00:00.37"Less join" version:
SQL> VARIABLE new_id_cnt NUMBER
SQL> EXEC :new_id_cnt := 10;
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.00
SQL> WITH my_table AS
2 (
3 SELECT num
4 FROM prs_elm
5 WHERE 1=1
6 )
7 , my_num AS
8 (
9 SELECT num AS num, LEAD(num) OVER (ORDER BY num) - num - 1 AS ct
10 FROM ( SELECT 0 AS num
11 FROM DUAL
12 UNION ALL
13 SELECT num
14 FROM my_table
15 UNION ALL
16 SELECT ( MAX(num) + :new_id_cnt + 1 ) AS num
17 FROM my_table
18 )
19 )
20 , my_cnt AS
21 (
22 SELECT LEVEL AS ct
23 FROM DUAL
24 CONNECT BY LEVEL <= :new_id_cnt
25 )
26 SELECT available_id
27 FROM
28 (
29 SELECT n.num + c.ct AS available_id
30 FROM my_num n
31 JOIN my_cnt c ON c.ct <= n.ct
32 WHERE n.ct >= 1
33 ORDER BY available_id
34 )
35 WHERE ROWNUM <= :new_id_cnt
36 ;
AVAILABLE_ID
3219
3261
3264
3269
3270
3275
3281
3288
3289
3290
10 rows selected.
Elapsed: 00:00:00.92PS: In Frank's code, there is a typo, <= should read as <.
Edited by: PuraVidaOTN on 04-feb-2013 22:49
What: To use tags to format the code.
Edited by: PuraVidaOTN on 04-feb-2013 22:56 -
How to : rownum and order by in select statement
Say I have a select statement with additional 'order by' clause.
The result set I want prepended by the rownum column.
But, and here comes the flaw, I want the rownum for the already ordered result set
not the unordered.
An example:
select firstname, lastname from myTable order by lastname;
When I add the rownum to the select clause,
'select rownum, firstname, lastname from myTable order by lastname;'
I might get something like:
20 Mike Adams
13 Nina Bravo
1 Tom Charlie
But I want the following result:
1 Mike Adams
2 Nina Bravo
3 Tom Charlie
I could now
'Select rownum, lastname, firstname from (select firstname, lastname from myTable order by lastname);
But I guess there is a better way!?!
which is the best way to accomplish that?
Thanks for your advice!>
'Select rownum, lastname, firstname from (select firstname, lastname from myTable order by lastname)
>
Well if you ask me there is very little difference between this query and the above query
select rownum, lastname, firstname from mytable;Because rownum is assigned before the order by. The difference is in your query you are assigning a rownum to an ordered resultset but still there is no guarantee oracle is going to read the data in an ordered fashion. In the second query rownum is assigned to an unordered resultset. Again it is the samething. So if you want to guarantee it then I will go for the following option
select row_number() over(order by lastname) rn, lastname, firstname from mytable
order by lastnameAlso check this link.
http://www.oracle.com/technology/oramag/oracle/07-jan/o17asktom.html
Regards
Raj
Edited by: R.Subramanian on Jan 13, 2009 6:20 AM -
Multi numbering range into Purch.order type
Dear All,
I need to maintain multi numbering range into one Purch.order type.
e.g.
Purch.Order type: 90NB
company : A
Number range: 9100000000
company : B
Number range: 3000000000
company : C
Number range: 3100000000
Is there anybody advice me?
Thanks & B.Rgds
Bishnu
02/06Hi
In standard sap, it is not possible to maintain different number range for same document type in different company codes.
try if any enhancement possible or not?
Regards,
Raman -
List the intercompany billing numbers from sale order numbers.
suppose i have a set of sale order numbers. is there any report can list the intercompany billing numbers related to those sale order numbers? i don't want to use VA03 because it can display only one sale order number.
thank you very much,
AnekHi Anek,
Run the transaction code VA05. Click on the Further Selection Criteria, Select the check box 'Sales Document Type' and click OK. System will ask for the Sale Document Type. ENter the inter company Document Type, Press Enter and select the date range press Enter.
System will list the orders.
Hope it helps. Let me know whether it resolves you issue.
Thanks & Regards,
Nagaraj Kalbavi -
Hi Gurus,
In my case, Number range object for Process Orders has been defined in CO82.
Suddenly some process orders have different naming 14XXXXXX instead of 72XXXXXX.
I would like to know what else affects the determination of Process order numbering.Dear Gameen,
One process order PI01 number range is 72XXXXXX and another process order PI02 number range is coming with this no.14XXXXXX. If you need to want PI02 also with 72XXXXXX number range then you can assign PI02 in 72XXXXXX number range.
Go to CO82, press F6 and select order type PI02 and press F2 then place the cursor on the number range 72XXXXXXX and select Element / Group. Order type Pi02 will be moved.
Check and revert back,
Regards / US -
Hi All
For a requirement of mine i am pulling data from the standard datasource 2LIS_11_VAITM into a DSO..but the problem is that few of the document numbers are missing and when i check that in R/3 those numbers are found along with the order qty..but these records are not available in the PSA too...and all the loads have run fine...
Actually i am pulling the Invoice data from other standard data source 2LIS_13_VDITM ..this has the ref field of the sale order number and there i am able to view the documnets which was not found in the order DSO
Can some only tell as to wat would be the problem in documents being lost...
Regards
ShilpaHi,
If you are loading using Sales Order Number ranges there is possibility that u missed any particular Number Range records.
OR
Might be lying in BW ques to load.
oR
Might be filtered by any filter or routine.
Thanks,
BPNR. -
Planned order numbers- reached maximum number
Hai,
We reached the maximum limit on Planned Order numbers (table PLAF). anyone had this situation before and if so how did you resolve it?
Thanks in advance,
SonaliHI
Go to T code SNRO then give NO range object PLAF and maintain the new NO Range for the object
Hope this will help u
Regards
Anupam Sharma -
Why after new changes in internal orders settings order number ranges lost?
Dear Gurus,
We have noticed that order number ranges are being lost from time to time.
Than we have analysed that sometimes it happens after new transfers with new orders settings.
Why the system behaves like that?
And how can we avoid this problem?
With best regards,
Kamila.The process is as below to assign/change number ranges to order types
Create Order type at KOT2 (KOT2_OPA) and enter Order Category ...say 01
Enter Order type name and description and SAVE
Select Number range Interval assingment Icon
At last row of the number range screen you can see your newly created Order Type
(Put the cursor on your order type and press F2) and Select the check box of group under which you need to assign and press F5
Now the newly created order type has been assigned and new number range has been assigned
So you can change existing order type also as mentioned above (even after posting made to that order types)
This could be the reason for changing number ranges to order types
Please take care while assigning number ranges to a new order types. Do not touch number ranges of existing order types
Srinivas -
Dear all,
The production server in my clients place is crashed a few days before... Then it was made up...
But the users feel many data are missing...
For example, In COOIS, If i enter an order type and execute, say nearly 1000 orders are coming..
SAy from 34500001000 to 34500002000.
But the order numbers are not serialised.. For exaple, the order numbers are 34500001000,34500001001,34500001002,34500001003,34500001009.......
SO the question is where do the orders 34500001004 to 34500001008 go..
Is there any possiblity that this can happen other than due to data loss...
please guide me..
THanks a lot..
sap125Dear,
Couple of things possible.
Check whether number range is set used for all the order type? Because you mentioned that you are running COOIS for a specific Order type, may be the missing numbers are used by other order types.
In standard SAP also there can always be a skip in numbers, due to the numbers which are available in buffer is not getting used during unexpected shut down etc... You can check the defination of the numbe range buffering using transaction SNRO- Object "AUFTRAG".
Please go through this thread where this was discussed earlier [Number Range - Number skip|number range object for production order;
Regards,
Prasobh -
Best Practice for Change Maintenance Order Number Range
Hello
We have decided that our Maintenance Orders will always start with the year of the open date. Example 201112345155
Every year we will need to change the number ranges
What is the best practice to change the order number range? What is the best approach here?
I have also another question. Why the "Current Number" is not incremental?
Thanks for the helpHi,
The current number can be explained by use of buffering of the numbers. Buffering is defined via transaction SNRO, the AUFTRAG object is relevant for orders. When buffering is active, a set of unused numbers are assigned to each application server.
In your example - The fiirst 20 numbers were taken from the available number range and assigned to the buffer (possible 10 numbers to each of two servers). As orders are created a number is assigned from the buffer. Once the buffer values are used a further set of numbers are taken from the number range and the current number is increased (by buffer value).
-Paul -
Dear All,
I have a Problem with process order Number ranges,
please find the sequence below.
21000200
21000220
21000240
21000260
21000280
21000300
21000320
21000321
21000322
21000340
21000360
21000380
21000381
21000400
21000401
21000402
21000403
21000420
21000421
21000422
21000423
Please anybody help me in this.
How to get contineus numbers.
Where I need to check, Please specify.
Thanks & Regards,
Anand.MDear,
Go to SNRO t-code.
In this t-code enter AUFTRAG object.
This object is for Order type.
Here you will get option No. of Numbers in buffer check it. This is the field which is responsible for number range buffering
Regards,
R.Brahmankar -
Hi Gurus,
How do you exactly add/create Number Range Groups for process orders?
Thanks,
KumarHi Kumar,
Assigning number range
There are two types of number assignment:
Internal
When saving a data record, the SAP System assigns a sequential number that lies within the corresponding number range interval.
External
When saving a data record, either you or an external system assigns a number. You need to ensure that the number lies within the corresponding number range interval.
In CO82..
Menu path Group -->maintain
In maintain number range group screen,
Group --> insert
Give text and from number and to number
say text = new order say For FG
range - 1xxxxxxxxx to 1999999999999 (tick ext check box if the range is external number range-manual input)
click on +
You can see your group at the end of list
In Not assigned group your new order type will be present
Place the curser on that order type and fallow the menu path as below
Edit -->select element
Select NEW order number range group check box
edit --> assign element group.
Now the number range is assigned to the order type. Save it, You will get a pop up, just ignore it.
Please try and come back.
Regards
R.Brahmankar -
Dear Oracle experts,
I am not getting the expected output when i use ROWNUM & ORDER BY clause in the same query.
Here is issue. Let us say, we have a table TEST with field last_update_date.
CREATE TABLE TEST(LAST_UPDATE_DATE DATE);
INSERT INTO TEST VALUES(TO_DATE('23-MAY-05'));
INSERT INTO TEST VALUES(TO_DATE('23-MAY-05'));
INSERT INTO TEST VALUES(TO_DATE('23-MAY-05'));
INSERT INTO TEST VALUES(TO_DATE('23-MAY-05'));
INSERT INTO TEST VALUES(TO_DATE('23-MAY-05'));
INSERT INTO TEST VALUES(TO_DATE('23-MAY-05'));
INSERT INTO TEST VALUES(TO_DATE('22-MAY-05'));
INSERT INTO TEST VALUES(TO_DATE('21-MAY-05'));
INSERT INTO TEST VALUES(TO_DATE('20-MAY-05'));
INSERT INTO TEST VALUES(TO_DATE('13-JUN-04'));
INSERT INTO TEST VALUES(TO_DATE('30-APR-05'));
INSERT INTO TEST VALUES(TO_DATE('09-MAR-05'));
INSERT INTO TEST VALUES(TO_DATE('12-MAY-05'));
select * from TEST
where trunc(LAST_UPDATE_DATE) >= to_date('09-MAR-05')
and trunc(LAST_UPDATE_DATE) <= to_date('22-MAY-05')
and rownum < 3
order by LAST_UPDATE_DATE;
The above query is supposed to return
09-MAR-05
30-APR-05
But it is returning
21-MAY-05
22-MAY-05
If i remove ROWNUM, then it returns in the correct order. But i want to restrict number of records in the same query.
Anybody can help me on this?.
Regards
GovindHello all,
I need yours expertise again.
I created FBI on last_update_date. It works fine.
When i run this query without order by clause, it takes only fraction of second to complete the process. If i add order by caluse, it takes for ever to complete the query. The table has 30 million records.
Anybody can help me on this?.
SELECT *
FROM (SELECT *
FROM TEST
where trunc(LAST_UPDATE_DATE) >= to_date('09-MAR-05')
and trunc(LAST_UPDATE_DATE) <= to_date('22-MAY-05')
order by LAST_UPDATE_DATE)
where rownum < 3
Regards
Govind -
Production Order No. Ranges
Hi expert ,
I was created order & save i got no 100001 ,
But in CO82 , current no range is 100021,
Can u told me where i can set buffer
Thanks in Advance
Thanks
UtkarshDear,
Go to CO82 keep cursor on your order Type say PP01 then go to header menu Interval--Change Current number range. Set it to 100001.
For Buffer
Go To SNRO and for Object AUFTRAG - Order Number Ranges reduce No. of numbers in
Buffer or set it to zero.
Please try and come back.
Regards
R.Brahmankar
Maybe you are looking for
-
How do I make gmail the default email program for email links in the Mozilla browser?
In previous versions of Mozilla I was able to click an email link , for example, on a craigslist listing and it would automatically open my gmail login page or if I was already logged in it would prompt a new email (compose) with the email field alre
-
How to get the universe a get data back in a Record structure
I am new to BI and im trying to figure a way to create replace our existing OWB datamart structure with Business Objects. I current work on a BI solution and we need to be able to query a universe in BI and get a result set back that we can then in t
-
Nokia N97 Mini - Network coverage disappeared
My Nokia N97 Mini, about 1 year old, suddenly decided it did not want to get any reception at all. I have travelled via train to different places for work and such and noticed it still was not getting reception. I have also tried restarting the phone
-
New GL feature question...
Group has 1000 investment entities, spread across 10 countries. Company is floated to develop the property and property is sold off in long run or it is given on lease. As per legal rule in most countries with 'EIN' number, each major property need
-
Hi, I try to make bar code in a PDF form. Question is, how can I make the value move from one field to another and bypassing something in between those field. For example: On the form on my end, I have Passport Number, Name, Exp. Date, DoB etc...the