Alternate of sql server TOP in oracle - oracle

How to get top 3 records in oracle pl sql?i am new to oracle,earlier i have used sql server.
My requirement is to get distinct top 3 records of Column X.

Try this to retrieve the Top N records from a query, you can use the following syntax::-
SELECT *
FROM (your ordered query) alias_name
WHERE rownum <= Rows_to_return
Example:-
SELECT *
FROM (select * from suppliers ORDER BY supplier_name) suppliers2
WHERE rownum <= 3

This may help you
SELECT ename, sal
FROM ( SELECT ename, sal, RANK() OVER (ORDER BY sal DESC) sal_rank
FROM emp )
WHERE sal_rank <= 3;

Related

Oracle SQL -- Finding count of rows that match date maximum in table

I am trying to use a query to return the count from rows such that the date of the rows matches the maximum date for that column in the table.
Oracle SQL: version 11.2:
The following syntax would seem to be correct (to me), and it compiles and runs. However, instead of returning JUST the count for the maximum, it returns several counts more or less like the "HAIVNG" clause wasn't there.
Select ourDate, Count(1) as OUR_COUNT
from schema1.table1
group by ourDate
HAVING ourDate = max(ourDate) ;
How can this be fixed, please?
You can use:
SELECT MAX(ourDate) AS ourDate,
COUNT(*) KEEP (DENSE_RANK LAST ORDER BY ourDate) AS ourCount
FROM schema1.table1
or:
SELECT ourDate,
COUNT(*) AS our_count
FROM (
SELECT ourDate,
RANK() OVER (ORDER BY ourDate DESC) AS rnk
FROM schema1.table1
)
WHERE rnk = 1
GROUP BY ourDate
Which, for the sample data:
CREATE TABLE table1 (ourDate) AS
SELECT SYSDATE FROM DUAL CONNECT BY LEVEL <= 5 UNION ALL
SELECT SYSDATE - 1 FROM DUAL;
Both output:
OURDATE
OUR_COUNT
2022-06-28 13:35:01
5
db<>fiddle here
I don't know if I understand what you want. Try this:
Select x.ourDate, Count(1) as OUR_COUNT
from schema1.table1 x
where x.ourDate = (select max(y.ourDate) from schema1.table1 y)
group by x.ourDate
One option is to use a subquery which fetches maximum date:
select ourdate, count(*)
from table1
where ourdate = (select max(ourdate)
from table1)
group by ourdate;
Or, a more modern approach (if your database version supports it; 11g doesn't, though):
select ourdate, count(*)
from table1
group by ourdate
order by ourdate desc
fetch first 1 rows only;
You can use this SQL query:
select MAX(ourDate),COUNT(1) as OUR_COUNT
from schema1.table1
where ourDate = (select MAX(ourDate) from schema1.table1)
group by ourDate;

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

Oracle Missing right parenthesis ORA-00907

Consider a database schema with three relations:
Employee (*eid:integer*, ename:string, age:integer, salary:real)
Works (*eid:integer*, *did:integer*, pct_time:integer)
Department(*did:integer*, dname:string, budget:real, managerid:integer)
Query the view above to find the name of the manager who manages most employees. If thesame employee works in several departments, that employee is counted once in each of the
departments. The manager is included in the count the same as all other employees, i.e., based
on his or her records in the Works table.
Why do I get this error:
ORDER BY SUM (EmpCount) DESC)
*
ERROR at line 6:
ORA-00907: missing right parenthesis
Here is my query:
SELECT distinct(MgrName)
FROM ManagerSummary
WHERE MgrID = (SELECT MgrID
FROM ManagerSummary
GROUP BY MgrID
ORDER BY SUM (EmpCount) DESC
LIMIT 1 );
The view is:
CREATE VIEW ManagerSummary (DeptName, MgrID, MgrName, MgrSalary, EmpCount)
AS SELECT d.dname, d.managerid, e.ename, e.salary,
(SELECT COUNT (w.did)
FROM works w
WHERE w.did = d.did
GROUP BY w.did)
FROM employee e, department d WHERE d.managerid = e.eid;
Thank you
Update: Changing LIMIT 1 for WHERE ROWNUM = 1 doesn't help
Try this
SELECT DISTINCT (MgrName)
FROM ManagerSummary
WHERE MgrID = (SELECT MgrId
FROM ( SELECT MgrId, SUM (empcount) AS maxemp
FROM ManagerSummary
GROUP BY MgrId
ORDER BY SUM (empcount) DESC)
WHERE ROWNUM = 1)
You seem to want the name of the manager that has the most employees.
My guess is that you can do this in Oracle as:
select ms.MgrName
from (select ms.*
from ManagerSummary ms
order by EmpCount desc
) ms
where rownum = 1;
It is hard for me to envision a table called ManagerSummary that would have more than one row per MgrId. That's why I don't think aggregation is necessary.
SELECT mgrname
FROM (SELECT mgrname, numemps
FROM (SELECT mgrname, count(*) numemps
FROM mgrsummary
GROUP BY mgrname)
ORDER BY NUMEMPS desc);
Just noticed - this is based on a view. This is ~not~ going to perform well.

Row num is not working for duplicate columns while pagination

Code is written below, multiple nested query:
select *
from
(select employee_id,employee_id
from employees) a
where rownum <= 5
)
where rnum >= 10
If i give duplicate columns in the select its giving "column ambiguously defined" error.
employee_id,employee_id, rownum rnum
Firstly, your query is incorrect since you have ambiguously defined the columns. It will throw ORA-00918: column ambiguously defined.
You must use proper ALIAS to avoid the error. For example,
SELECT departments.department_id AS "dept_id",
employees.department_id AS "emp_Dept_id"
FROM...
Secondly, it is not at all a pagination query. Since you are alwyas going to pick random rows as there is no ORDER BY clause. You are not ordering the rows.
where rownum <= 5
where rnum >= 10
At last, how on earth could you try to fetch the rows beyond 10 when you have fetched ONLY 5 rows in the inner query? It will ALWAYS return zero rows.
The correct way of paging through data is:
SQL> SELECT empno
2 FROM (SELECT empno, rownum AS rnum
3 FROM (SELECT empno
4 FROM emp
5 ORDER BY sal)
6 WHERE rownum <= 8)
7 WHERE rnum >= 5;
EMPNO
----------
7654
7934
7844
7499
SQL>
when you give a.* it means you are trying to refer two columns with same name in a table which is not permitted.The column names in a table are unique
So select employee_id,employee_id from employees is not a problem
but
select a.* from (select employee_id,employee_id from employees)a is a problem
the sqlfiddle here
Also if you want records from 10 to 15 in your query then use like the below
select * from
(select a.*,Rownum rnum from
(select employee_id as emp_id1,employee_id as emp_id2
from employees order by 1)
a where rownum <= 15 ) where rnum >= 10
EDIT1:- If duplicate column is required use like the below
with emp1 as (select employee_id from employees),
emp2 as (select * from
(select a.*,rownum rnum from emp1 a order by 1)
where rownum <=15)
select b.*,c.*
from emp1 b,emp2 c
where b.employee_id=c.employee_id
and c.rnum >=10

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