Paging (oracle database) - oracle

I need to create request to oracle database from my C# code what will select rows for pages at web site. I want for example for get rows from 100 to 200 for second page.
I found some code what real works
SELECT * FROM
(
SELECT a.*, rownum r__
FROM
(
SELECT * FROM ORDERS WHERE CustomerID LIKE 'A%'
ORDER BY OrderDate DESC, ShippingDate DESC
) a
WHERE rownum < ((pageNumber * pageSize) + 1 )
)
WHERE r__ >= (((pageNumber-1) * pageSize) + 1)
It works, I can use it when change this block inside wrap
SELECT * FROM ORDERS WHERE CustomerID LIKE 'A%'
ORDER BY OrderDate DESC, ShippingDate DESC
But how does it work? I can't understand. I'm familiar with SQL requests but what is
SELECT a.*, rownum r__
and what is
) a
after FROM wrap?
Can you be so kind to explain me this wrap?

select a.*, rownum ->Select all records from table/table alias a, along with rownumber, so you can select a subset.
(SELECT * FROM ORDERS WHERE CustomerID LIKE 'A%'
ORDER BY OrderDate DESC, ShippingDate DESC) a
Creates 'a' as a table alias allowing you to treat it as a table in outer select table.
As a note, select * is considered bad practice as changes to the table structure will likely break your code.

Related

FROM keyword not found where expected while filtering data

I got one error
ORA-00923: FROM keyword not found where expected
Here is my query
SELECT * FROM
(SELECT *, (SELECT COUNT(*) FROM invoices) AS numberOfRows
FROM invoices ORDER BY Id DESC) WHERE rownum <= 1
I am begginer in Oracle SQL, but as I see here I have FROM keyword and it looks everythink OK.
I try to modify this query something like but still get another error
ORA-00933: SQL command not properly ended
SELECT * FROM
(SELECT COUNT(*) FROM invoices) AS numberOfRows
FROM invoices ORDER BY Id DESC) WHERE rownum <= 1
What is wrong in first select query ? What is missing ? Since I check everything, start from special character ( . , )
Also I try this kind of solution and get error
ORA-00936: missing expression
SELECT * FROM (SELECT , (SELECT COUNT() FROM invoices) AS numberOfRows FROM invoices ORDER BY Id DESC) WHERE rownum <= 1
The railroad diagram in the documentation:
... shows that you can either use * on its own, or <something>.* along with other columns or expressions. So you need to precede your * with the table name or an alias:
SELECT * FROM
(SELECT i.*, (SELECT COUNT(*) FROM invoices) AS numberOfRows
FROM invoices i ORDER BY Id DESC) WHERE rownum <= 1
If you're on a recent version of Oracle you can do this much more simply with:
select i.*, count(*) over () as numberOfRows
from invoices i
order by id desc
fetch first row only
On older version you still need a subquery, but only one level:
select *
from (
select i.*, count(*) over () as numberOfRows
from invoices i
order by id desc
)
where rownum = 1
db<>fiddle
looks like the FROM is missing from this select "SELECT *,"
SELECT * FROM
(SELECT , (SELECT COUNT() FROM invoices) AS numberOfRows
FROM invoices ORDER BY Id DESC) WHERE rownum <= 1

T-SQL to PL/SQL - Use temporary variables and the "INTO" expression to search the total of a query in Oracle DB

In sql below I return the search between the tables and then return the total of this already paginated.
The need to return this total is to paginate
That query is using sql server.
Sql server:
SELECT
bu.Id as 'BarcoUsuarioId',
Barco_Id as 'BarcoId',
bu.Usuario_Id as 'UsuarioId',
barco.Nome as 'NomeBarco'
into #tmpBarcoUsuario
FROM BARCO_USUARIO AS bu
inner join BARCO as barco on barco.Id = bu.Barco_Id
where bu.Usuario_Id = #usuarioId
declare #totalEmbarcacoes as int = (select count(*) from #tmpBarcoUsuario);
select
BarcoUsuarioId,
BarcoId,
UsuarioId,
NomeBarco,
#totalEmbarcacoes as TotalEmbarcacoes from #tmpBarcoUsuario
order by BarcoId
OFFSET #pageSize *(#pageNumber - 1) ROWS
fetch next #pageSize ROWS ONLY";
However, when using the Oracle database, I having some difficulty.
As can be seen in sql below, I already made the pagination query in oracle DB:
Oracle:
SELECT *
FROM(
SELECT ROWNUM rnum, b.*
FROM (
SELECT
barcoUser.ID BarcoUsuarioId ,
barcoUser.BARCO_ID BarcoId ,
barcoUser.USARIO_ID UsuarioId ,
barco.NOME NomeBarco
FROM BARCO_USUARIO barcoUser INNER JOIN EMBARCACAO barco ON barco.ID = barcoUser.BARCO_ID
WHERE (barcoUser.USARIO_ID=:usuarioId)ORDER BY BarcoId DESC
)b
)WHERE RNUM between :PageSize * (:PageNumber - 1) AND (:PageSize * :PageNumber)";
but how would I do to return the total of all this already paginated, as was done in sql server?
You can use the analytic count(*) function
SELECT *
FROM(
SELECT ROWNUM rnum, b.*
FROM (
SELECT
barcoUser.ID BarcoUsuarioId ,
barcoUser.BARCO_ID BarcoId ,
barcoUser.USARIO_ID UsuarioId ,
barco.NOME NomeBarco ,
count(*) over () TotalCount
FROM BARCO_USUARIO barcoUser
INNER JOIN EMBARCACAO barco ON barco.ID = barcoUser.BARCO_ID
WHERE (barcoUser.USARIO_ID=:usuarioId)
ORDER BY BarcoId DESC
)b
)
WHERE RNUM between :PageSize * (:PageNumber - 1)
AND (:PageSize * :PageNumber)
Note that Oracle has supported the OFFSET FETCH syntax since 12c if you want to minimize the changes between database engines. The rownum approach, however, may be faster than the OFFSET FETCH approach.

oracle sql pagination with total pages or total entries

I'm trying to access paginated results from a DB. Following the below query:
SELECT * FROM
(
SELECT a.*, rownum r__
FROM
(
SELECT * FROM ORDERS WHERE CustomerID LIKE 'A%'
ORDER BY OrderDate DESC, ShippingDate DESC
) a
WHERE rownum < ((pageNumber * pageSize) + 1 )
)
WHERE r__ >= (((pageNumber-1) * pageSize) + 1)
from here , I am able to achieve pagination.
I modified the query like below inorder to get total counts as well :
SELECT * FROM
(
SELECT a.*, rownum r__ , count(OrderDate)
FROM
(
SELECT * FROM ORDERS WHERE CustomerID LIKE 'A%'
ORDER BY OrderDate DESC, ShippingDate DESC
) a group by OrderDate
)
WHERE r__ between (pageNumber * pageSize )+ 1 and (pageNumber *pageSize) + pageSize;
But I also want to calculate the total number of pages and if the requested page is the last page as well. I tried to get the COUNT of the inner query so that I can calculate the total pages inside my code, but I could not get it. I've tried by COUNT(ORDERDATE) and grouping but it does not work.
Please tell me how I can achieve this.
I would use analytic functions to do the work you're trying to do, e.g.:
SELECT res.*,
CEIL(total_num_rows/pagesize) total_num_pages
FROM (SELECT o.*,
row_number() OVER (ORDER BY orderdate DESC, shippingdate DESC) rn,
COUNT(*) OVER () total_num_rows
FROM orders o
WHERE customerid LIKE 'A%') res
WHERE rn BETWEEN (pagenumber - 1) * pagesize + 1 AND pagenumber * pagesize;
N.B. untested.
The query does the pagination by using the row_number() analytic function to assign a number to each row, across the specified groups and in the specified order. Since we don't have a partition by clause in the OVER section, the function is working across the entire set of rows.
Similarly, we use the count() analytic function to get the count of the rows across the specified groups - and again, as we haven't specified any partition by clause, the function works across the entire set of rows.
Now you have those numbers, it's a simple matter to do the pagination and find the total number of pages.
If you are on Oracle 12.1 or later, this becomes simpler:
select o.*
, 'Page ' || pagenumber || ' of ' || ceil(count(*) over () / pagesize) as pagecount
from orders o
where customerid like 'T%'
order by orderdate desc, shippingdate desc
offset (pagenumber -1) * pagesize rows fetch next pagesize rows only;
The page count column will report values like Page 2 of 34.

Oracle query with rownum and orderBy return wrong records

I got an confusing result when working with rownum of Oracle10g.
first query
select * from A where name like '%test' order by name asc
==> return 1 record
second query with rownum
select * from (
select * from A where name like '%test'
order by name asc
)
where rownum <= 2
==> return 2 records
If I remove 'order by' then it will return 1 record.
Any one can help me to explain this behavior?
maybe you wanted this functionality:
select * from (
select X.*, rownum r from (
select * from A where name like '%test'
order by name asc
) X
)
where r <= 2
or alternatively
select * from (
select A.*, ROW_NUMBER() OVER (ORDER BY name) r
from A where name like '%test'
)
where r <= 2

Using rownum with the combination of between keyword

I have seen this Oracle SQL query for using rownum with the combination of between keyword .
select *
from
( select rownum rnum, a.*
from (your_query) a
where rownum <= :M )
where rnum >= :N;
in order to get rows n through m from 'your query.'
I want to try it , Could anybody please tell me how can i get the data from an Emp table to fetch records from 4 to 8 Records
select *
from
( select rownum rnum, a.*
from (select * from emp) a
where rownum <= 4 )
where rnum >= 8;
But this isn't working , could anybody please tell me why .
Thank you very much .
This is because you are limiting your query to <=4 rows, so when you filter to show records >=8 there are only 4 records to look at....
Invert the numbers and you should see a result:
select *
from
( select rownum rnum, a.*
from (select * from emp) a
where rownum <= 8 )
where rnum >= 4;
If I had to guess, I'd say that the reason you're not seeing what you expect (in addition to having the operators backwards, as pointed out by #diagonalbatman) is that you didn't tell the database what order you wanted the rows in. You're essentially telling the database to return any 5 rows. You can't even be sure that this query will always return the same five rows. Any time you're getting a subset like this, you should use an order by clause in the innermost query, so that the sort is applied before the rownum values are issued:
SELECT *
FROM (SELECT ROWNUM rnum, a.*
FROM (SELECT *
FROM emp
ORDER BY emp_id) a
WHERE ROWNUM <= 8)
WHERE rnum >= 4;
When you are querying the whole data in the inner statement (if you have huge data amounds, no good idea!) you could as well use the BETWEEN keyword.
SELECT *
FROM
(SELECT rownum AS rnum,
a.*
FROM EMP) a
WHERE rnum BETWEEN 4 AND 8;

Resources