This question already has answers here:
How to use the 'as' keyword to alias a table in Oracle?
(2 answers)
Closed last year.
select * from(select e.*,dense_rank() over(partition by dept_name order by salary desc) as Top_salaried
from employee e) as B where Top_salaried <= 3;
I have the above query that fetches top 3 salary from each dept
above is working fine PostgreSQL
when i try to exec the same in oracle it throws error
SQL command not properly ended
Can anyone please help me with this
how do i need to modify it in oracle
In Oracle, table aliases don't allow the AS keyword (but column aliases do, such as as top_salaried). So:
SELECT *
FROM (SELECT e.*,
DENSE_RANK ()
OVER (PARTITION BY dept_name ORDER BY salary DESC) AS top_salaried
FROM employee e) b --> no "as" here
WHERE top_salaried <= 3;
Related
This question already has answers here:
How do I limit the number of rows returned by an Oracle query after ordering?
(14 answers)
When did oracle start supporting "top": select top ? p2_.PRODUCT_ID from PRODUCT?
(3 answers)
Closed 11 months ago.
I am trying to convert this from SQL server to oracle:
select top 1 #StatusCount=Count(*),#logidnew=logid
from KioskStatuslog
where kioskid=#KioskId
and cast(logdate as date)=Cast(getdate() as date) --and lanstatus=#LANStatus
group by logid order by logid desc
TOP(n) is SQL Server's propriatary counterpart to standard SQL's FETCH FIRST n ROWS.
select count(*) as status_count, logid
from kioskstatuslog
where kioskid = :kioskid
and trunc(logdate) = trunc(sysdate)
group by logid
order by logid desc
fetch first row only;
As to
and trunc(logdate) = trunc(sysdate)
it is recommended to use
and logdate >= trunc(sysdate) and logdate < trunc(sysdate) + interval '1' day
instead, so the DBMS may use an index on that column if such exists. (Of course you could also have an index on trunc(logdate) instead and keep the simpler expression.)
Should be something among the lines:
SELECT *
FROM (SELECT COUNT(1), LOGID
FROM KIOSKSTATUSLOG
WHERE KIOSKID = &KIOSKID --argument
AND TRUNC(TO_DATE(LOGDATE,<FORMAT_OF_THE_DATE>)) = TRUNC(SYSDATE)
AND LANSTATUS = &LANStatus --argument
GROUP BY LOGID
ORDER BY LOGID DESC)
WHERE ROWNUM = 1;
This question already has answers here:
Oracle SELECT TOP 10 records [duplicate]
(6 answers)
Closed 2 years ago.
Is there any way to find the last 500 records from a table with out using union, union all or minus function?
Can we achieve this using rank, row_number or dense_rank functions in sql.
Thanks
Rakesh
Teradata uses TOP
SELECT TOP 500 * FROM table ORDER BY your_column
Oracle 12c+ uses FETCH:
SELECT * FROM TABLE ORDER BY your_column DESC FETCH FIRST 500 ROWS ONLY
Older oracle uses rownum, and the orderby must be done in a subquery:
SELECT * FROM (SELECT * FROM TABLE ORDER BY your_column DESC) WHERE rownum <= 500
You could use ROW_NUMBER in a DB that supports it:
SELECT * FROM (SELECT *, ROW_NUMBER() OVER(ORDER BY your_column DESC) rn FROM TABLE) WHERE rn <= 500
your_column is used to determine "last"ness.. It needs to be something that sorts sensibly, like a numeric id, date etc
Edit:
Your interviewer expected you to use analytical functions. Here's what it would look like:
SELECT *
FROM
(
SELECT *, ROW_NUMBER() OVER(ORDER BY your_column DESC) as rn
FROM table
) x
WHERE x.rn < 501
Not that it still needs an order by; here's what happens when you skip it:
You can use the SQL limit with orderby desc to get the last N number of records.
select * from tbl_name order by id desc limit N;
I have a table in Oracle SQL whose ids are in increasing, sequential order, but there are gaps in the ids due to editing, e.g. the ids are currently something like
22
23
24
32
33
44
...etc
I check one post and the solution provided was as below:
update (select t.*, row_number() over (order by id) as newid) toupdate
set id = newid
Solution Provided earlier.
Now my query:
1) I guess the "From clause" is missing in the above query.
Updated query:
update (select t.*,
row_number() over (order by emp_id) as newid
from employee t ) toupdate
set emp_id = newid;
2) When i run the above query, it gives me error "data Manipulation operation not legal on this view".
Can anyone explain how the mentioned solutions worked here. can anyone post the full update query. Thanks.
This solution to the same question you referenced shows how to do it:
update employee set emp_id = (
with tab as (
select emp_id, rownum r
from (select emp_id from employee order by emp_id)
)
select r from tab where employee.emp_id = tab.emp_id
);
That works. You cannot update a view that contains an analytic function like row_number - see Oracle 12C docs, look for "Notes on Updatable Views".
You could use a merge, but you'd need to join on something other than emp_id as you want to update that column. If there are no other unique columns you can use the rowid:
merge into employee target
using (select rowid, row_number() over (order by emp_id) as emp_id from employee) source
on (source.rowid = target.rowid)
when matched then update set target.emp_id = source.emp_id;
I think this would be easiest approach :
update mytable set id = ROWNUM;
Oracle SQL - update ids in oracle sql to be in sequential order
I do understand the meaning of this statement but I don't understand why do we need this?
This is equivalent to
select first_Name, last_name from employees
I can see this type of statements in many examples. Can you please explain when we need this? In practical do we use this type of statements?
Can you please explain when we need this?
These are called Derived Tables.
A "derived table" is essentially a statement-local temporary table
created by means of a subquery in the FROM clause of a SQL SELECT
statement. It exists only in memory and behaves like a standard view
or table.
In SQL, subqueries can only see values from parent queries one level deep.
In practical do we use this type of statements?
The most common use of it is the classic row-limiting query using ROWNUM.
Row-Limiting query:
SELECT *
FROM (SELECT *
FROM emp
ORDER BY sal DESC)
WHERE ROWNUM <= 5;
Pagination query:
SELECT eno
FROM (SELECT e.empno eno,
e.ROWNUM rn
FROM (SELECT empno
FROM emp
ORDER BY sal DESC) e)
WHERE rn <= 5;
This kind of statement is useless, you're right, but there are many occasions when you need a subselect because you can't do everything in one statement. Of the top of my head I'd be thinking about for instance, combining aggregate functions, get the min, max and avg of a sum
select min(t.summed), max(t.summed), avg(t.summed)
from (select type, sum(value) as summed from table1 group by type) t
this is just from the top of my head, but I did encounter many occasions where subselects in the from clause were necessary. Once the statements are complex enough you'll see it.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Paging with Oracle
I try to select data starting from 11 row. and i used
select e_name from copy where rownum>10;
this will not display's anything..
please help me to select 11th row to 15th row in my table
You cannot use rownum like that, you need to wrap everything into a derived table:
select *
from (
select *,
rownum as rn
form your_table
order by some_column
)
where rn between 11 and 15
You should use an order by in the inner query because otherwise you will not get consistent results over time. Rows in a relational table do not have any ordering so the database is free to return the rows in any order it feels approriate.
Please read the manual for more details. The reason your query isn't working is documented there with examples.
http://docs.oracle.com/cd/E11882_01/server.112/e26088/pseudocolumns009.htm#i1006297
You have to use like
select e_name
from (select e_name,rownum rno from copy)
where rno > 10 and rno < 16
Sample Example
you could use analytic function row_number() as well. Please consider http://docs.oracle.com/cd/B19306_01/server.102/b14200/functions137.htm
First write the query which will select all the rows like this:-
select ename from employee
Now add a rownum column to your query, rownum will help you to identify the number of row in your query result
select rownum r,ename from employee
Now make your query as a sub query and apply the range on 'r' (rownum)
select * from (selecr rownum r, ename from employee) subq where subq.r between 11 and 15