Clarification on "rownum" - sql

I have a table Table1
Name Date
A 01-jun-2010
B 03-dec-2010
C 12-may-2010
When i query this table with the following query
select * from table1 where rownum=1
i got output as
Name Date
A 01-jun-2010
But in the same way when i use the following queries i do not get any output.
select * from table1 where rownum=2
select * from table1 where rownum=3
Someone please give me guidance why it works like that, and how to use the rownum.

Tom has an answer for many Oracle related questions
In short, rownum is available after the where clause has been applied and before the order by clause is applied.
In the case of RowNum=2, the predicate in the where clause will never evaluate to true as RowNum starts at 1 and only increases if records matching the predicate can be found.

Adding rownums is one of the last things done after the result set has been fetched from the database. This means that the first row will always have rownum 1. Rownum is better used when you want to limit the result set, for instance when doing paging.
See this for more: http://www.orafaq.com/wiki/ROWNUM

(Not an Oracle expert by any means)
From what I understand, rownum numbers the rows in a result set.
So, in your example:
select * from table1 where rownum=2
How many rows are there going to be in the result set? Therefore, what rownum would be assigned to such a row? Can you see now why no result is actually returned?
In general, you should avoid relying on rownum, or any features that imply an order to results. Try to think about working with the entire set of results.
With that being said, I believe the following would work:
select * from (select rownum as rn,table1.* from table1) as t where t.rn = 2
Because in that case, you're numbering the rows within the subquery.

Related

SQL Server - Pagination Without Order By Clause

My situation is that a SQL statement which is not predictable, is given to the program and I need to do pagination on top of it. The final SQL statement would be similar to the following one:
SELECT * FROM (*Given SQL Statement*) b
OFFSET 0 ROWS FETCH NEXT 50 ROWS ONLY;
The problem here is that the *Given SQL Statement* is unpredictable. It may or may not contain order by clause. I am not able to change the query result of this SQL Statement and I need to do pagination on it.
I searched for solution on the Internet, but all of them suggested to use an arbitrary column, like primary key, in order by clause. But it will change the original order.
The short answer is that it can't be done, or at least can't be done properly.
The problem is that SQL Server (or any RDBMS) does not and can not guarantee the order of the records returned from a query without an order by clause.
This means that you can't use paging on such queries.
Further more, if you use an order by clause on a column that appears multiple times in your resultset, the order of the result set is still not guaranteed inside groups of values in said column - quick example:
;WITH cte (a, b)
AS
(
SELECT 1, 'a'
UNION ALL
SELECT 1, 'b'
UNION ALL
SELECT 2, 'a'
UNION ALL
SELECT 2, 'b'
)
SELECT *
FROM cte
ORDER BY a
Both result sets are valid, and you can't know in advance what will you get:
a b
-----
1 b
1 a
2 b
2 a
a b
-----
1 a
1 b
2 a
2 b
(and of course, you might get other sorts)
The problem here is that the *Given SQL Statement" is unpredictable. It may or may not contain order by clause.
your inner query(unpredictable sql statement) should not contain order by,even if it contains,order is not guaranteed.
To get guaranteed order,you have to order by some column.for the results to be deterministic,the ordered column/columns should be unique
Please note: what I'm about to suggest is probably horribly inefficient and should really only be used to help you go back to the project leader and tell them that pagination of an unordered query should not be done. Having said that...
From your comments you say you are able to change the SQL statement before it is executed.
You could write the results of the original query to a temporary table, adding row count field to be used for subsequent pagination ordering.
Therefore any original ordering is preserved and you can now paginate.
But of course the reason for needing pagination in the first place is to avoid sending large amounts of data to the client application. Although this does prevent that, you will still be copying data to a temp table which, depending on the row size and count, could be very slow.
You also have the problem that the page size is coming from the client as part of the SQL statement. Parsing the statement to pick that out could be tricky.
As other notified using anyway without using a sorted query will not be safe, But as you know about it and search about it, I can suggest using a query like this (But not recommended as a good way)
;with cte as (
select *,
row_number() over (order by (select 0)) rn
from (
-- Your query
) t
)
select *
from cte
where rn between (#pageNumber-1)*#pageSize+1 and #pageNumber*#pageSize
[SQL Fiddle Demo]
I finally found a simple way to do it without any order by on a specific column:
declare #start AS INTEGER = 1, #count AS INTEGER = 5;
select * from (SELECT *,ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS fakeCounter
FROM (select * from mytable) AS t) AS t2 order by fakeCounter OFFSET #start ROWS
FETCH NEXT #count ROWS ONLY
where select * from mytable can be any query

Confused syntax in Where clause

what does the line (rowid,0) mean in the following query
select * from emp
WHERE (ROWID,0) in (
select rowid, mod(rownum,2) from emp
);
i dont get the line WHERE (ROWID,0).
what is it?
thanx in advance
IN clause in Oracle SQL can support column groups. You can do things like this:
select ...
from tab1
where (tab1.col1, tab1.col2) in (
select tab2.refcol1, tab2.refcol2
from tab2
)
That can be useful in many cases.
In your particular case, the subquery use for the second expression mod(rownum,2). Since there is no order by, that means that rownum will be in whichever order the database retrieves the rows - that might be a full table scan or a fast full index scan.
Then by using mod every other row in the subquery gets the value 0, every other row gets the value 1.
The IN clause then filters on second value in the subquery being equal to 0. The end result is that this query retrieves half of your employees. Which half will depend on which access path the optimizer chooses.
Not sure what dialect of sql you're using, but it appears that since the subquery in the IN clause has two columns in the select list, then the (ROWID,0) indicates which columns align with the subquery. I have never seen multiple columns in an IN statment's select list before.
This is a syntax used by some databases (but not all) that allows you to do in with multiple values.
With in, this is the same as:
where exists (select 1
from emp e2
where e2.rowid = emp.rowid and
mod(rownum, 2) = 0
)
I should note that if you are using Oracle (which allows this syntax), then you are using rownum in a subquery with no order by. The results are going to be rather arbitrary. However, the intention seems to be to return every other row, in some sense.

Clarifying rownum order of operations in Oracle

According to this link, when using rownum in a query, it is called in the following order of operations.
The FROM/WHERE clause goes first.
ROWNUM is assigned and incremented to each output row from the FROM/WHERE clause.
SELECT is applied.
GROUP BY is applied.
HAVING is applied.
ORDER BY is applied.
I want to know where the AND would be categorized on this list. Would it be evaluated at the same time as the WHERE? What if the WHERE has a rownum and the AND does not?
The AND has no role in this. When result set is being constructed, the rownum is assigned to the results before outermost ordering. Filtering on ROWNUM is a hard stop from feeding results up from deeper in the execution plan. Therefore for example a construct like where rownum > 5 returns no rows.
Hopefully this helps. If not, please elaborate in your question and/or explain why you are asking. There are alternatives that are sometimes better, such as row_number().
I just had an update not work that had where field_value is not null and rownum = 1.
since rownum = 1 was for a row that had field_value = null that was the row it tired to return and then no action occurred in the update.
So with in the Where clause there is also an order of operation.
need to put () around it or make it a sub query to be sure rownum is on the results of the other parts of the where cause.
I used a distinct instead of rownum = 1 for my case.

What's the meaning of this sql statement (order by count(*))?

What could be the meaning of this sql statement ?
select * from tab1 order by (select count(*) from tab2) desc
The below line just returns the number of rows in tab2, which is some constant number
select count(*) from tab2
Consider the columns numbered 1 through n where n is the last column.
select * from tab1 order by 1
would order by the first column
select * from tab1 order by 2
would order by the second column and etc.
If n is larger than the number of columns then you'll run into a problemEDIT
You are using a subquery however and having
select * from tbl1 order by (select 1000)
does not cause a problem if you have <1000 columns, it seems to do nothing; the query may be missing some information
The result is to order by the column whose index is the count returned by the inner query in the ORDER BY clause. Whoever wrote this, especially without a comment, should be hanged by body parts important for reproduction.
The answer is based in Microsoft SQL functionality [edit:] where subquery in ORDER BY (subquery) expression indicates sort value.
Here's how I see it: since tab2 is not linked to tab1 in a subquery, the SQL can be reduced to:
select * from tab1 order by (SELECT <CONSTANT>) desc
therefore it's equivalent to:
select * from tab1
Quite frankly all that query is going to do is return all records from tab1 in some unknown order.
The order by clause is a bit asinine because the value returned will always be the count of all records in tab2.
I suspect it's missing a where clause on the (select count(*) from tab2) part. Something along the lines of (select count(*) from tab2 t where t.tab1id = tab1.id) Although it's hard to say without knowing the structure of those two tables.
The ORDER BY is equivalent to ORDER BY 'X'; that is, it has no effect. It does not order by the column number referenced by the count(*) in the second query -- it is not equivalent to order by 3 if the second table has three rows.
See fiddles for Oracle, MySQL, and SQL Server. If the ORDER BY was based on the count(*), the result should then be sorted by the third column. None of them are. Also, a count(*)+100 has no effect.

fetching data using rownum in oracle

I have a query in oracle to fetch data from table using rownum but i didn't get any data.
My query is like this :
select * from table-name where rownum<5
is this is a wrong query to fetch data whose row number is less than 5.
when i used query like :
select * from table-name where rownum<=4
than it will gives a result record.
My question is what is wrong here with ?
Is this is syntax error or anything else??..
rownum is a pseudo column that counts rows in the result set after the where clause has been applied.
SELECT table_name
FROM user_tables
WHERE rownum > 2;
TABLE_NAME
------------------------------
0 rows selected
However, this query will always return zero rows, regardless of the number of rows in the table.
To explain this behaviour, we need to understand how Oracle processes ROWNUM. When assigning ROWNUM to a row, Oracle starts at 1 and only increments the value when a row is selected; that is, when all conditions in the WHERE clause are met. Since our condition requires that ROWNUM is greater than 2, no rows are selected and ROWNUM is never incremented beyond 1.
http://blog.lishman.com/2008/03/rownum.html
another stackoverflow link
Edited
this paragraph i find on oracle website which is much better
Conditions testing for ROWNUM values greater than a positive integer are always false. For example, this query returns no rows:
SELECT * FROM employees
WHERE ROWNUM > 1;
The first row fetched is assigned a ROWNUM of 1 and makes the condition false. The second row to be fetched is now the first row and is also assigned a ROWNUM of 1 and makes the condition false. All rows subsequently fail to satisfy the condition, so no rows are returned.
You can also use ROWNUM to assign unique values to each row of a table, as in this example:
Syntax seems correct to me.
However ROWNUM is calculated on result rows for example:
SELECT * FROM TABLE_NAME WHERE ROWNUM < 10 ORDER BY TABLE_FIELD ASC;
and
SELECT * FROM TABLE_NAME WHERE ROWNUM < 10 ORDER BY TABLE_FIELD DESC;
Will give you different results.
Each time a query is executed, for each tuple, Oracle assigns a ROWNUM which is scopet to that only query.
What are you trying to accomplish ?
Since for the reasons rahularyansharma mentions, rownum based queries won't always function the way you might expect, a way around this is to do something like
SELECT * from (SELECT rownum AS rn, TABLE_NAME.* FROM TABLE_NAME)
where rn > 5;
However, be aware that this will be a fairly inefficient operation when operating over large datasets.