We cannot use TOP command in SQL in ORACLE to get the top n sorted rows,as it doesn't support it. But there are ways of getting the result using rank() and rownum() but that requires and inner query. I want to know if there is any other way apart from using rownum()/rank() with inner query.
I don't know what "rownum()" is. The best way is the answer that #PinnyM deleted . . .
select *
from (<your query here>
order by <your ordering>
) t
where rownum < xx
This is much better than using row_number() or rank(), because rownum requires minimal processing for the value.
By the way, TOP is specific to SQL Server and Sybase. Other databases using LIMIT.
Related
I am using DBeaver to query a PostgreSQL database.
I have this query, it simply selects the highest id per Enterprise_Nbr. The query works but is really slow. Is there any way I can rewrite the query to improve performance.
I am using the querytool DBeaver because I don't have direct access to PostgreSQL. The ultimate goal is to link the PostgreSQL with PowerBi.
select *
from public.address
where "ID" in (select max("ID")
from public.address a
group by "Enterprise_Nbr")
Queries for greatest-n-per-group problems are typically faster if done using Postgres' proprietary distinct on () operator
select distinct on ("Enterprise_Nbr") *
from public.address
order by "Enterprise_Nbr", "ID" desc;
Your query could rewrite as: per each value of Enterprise_Nbr, retrieve row which there is not exists other rows that have same Enterprise_Nbr and greater ID.
SELECT *
FROM public.address a
WHERE NOT EXISTS (
SELECT 1
FROM public.address b
WHERE b.Enterprise_Nbr = a.Enterprise_Nbr AND b.ID > a.ID
)
Is there a way to make a simple GROUP BY query with SQL and not use COUNT,AVG or SUM? I want to show all columns and group it with a single column.
SELECT * FROM [SPC].[dbo].[BoardSFC] GROUP BY boardsn
The query above is working on Mysql but not on SQL, is there a way to achieve this? any suggestion would be great
UPDATE: Here is my data I just need to group them by boardsn and get imulti equals to 1
I thing you just understand 'group data' in a different way than it is implemented in sql server. You simply want rows that have the same value together in the result and that would be ordering not grouping. So maybe what you need is:
SELECT *
FROM [SPC].[dbo].[BoardSFC]
WHERE imulti = 1
ORDER BY boardsn
The query above is working on Mysql but not on SQL, is there a way to achieve this? any suggestion would be great
No, there is not. MySQL only lets you do this because it violates the various SQL standards quite egregiously.
You need to name each column you want in the result-set whenever you use GROUP BY. The SELECT * feature is only provided as a convenience when working with data interactively - in production code you should never use SELECT *.
You could use a TOP 1 WITH TIES combined with a ORDER BY ROW_NUMBER.
SELECT TOP 1 WITH TIES *
FROM [SPC].[dbo].[BoardSFC]
ORDER BY ROW_NUMBER() OVER (PARTITION BY boardsn ORDER BY imulti)
Or more explicitly, use ROW_NUMBER in a sub-query
SELECT *
FROM
(
SELECT *, ROW_NUMBER() OVER (PARTITION BY boardsn ORDER BY imulti) as RN
FROM [SPC].[dbo].[BoardSFC]
) q
where RN = 1
We are going to update our database from 10g to 12c. Before doing so we need to revisit our SQLs, and as a part of this we need to check the following behavior of GROUP BY
case 1:
SELECT abcd_pk,
COUNT(abcd_code),
ABCD_COUNT
FROM
(SELECT abcd_pk,
abcd_code,
(SELECT COUNT(abcd_code) FROM ABCD_TABLE
) "ABCD_COUNT"
FROM ABCD_TABLE
)
GROUP BY abcd_pk, ABCD_COUNT ;
WORKS IN 10G
WORKS IN 12C
case 2:
SELECT abcd_pk,
COUNT(abcd_code),
ABCD_COUNT
FROM
(SELECT abcd_pk,
abcd_code,
(SELECT COUNT(abcd_code) FROM ABCD_TABLE
) "ABCD_COUNT"
FROM ABCD_TABLE
)
GROUP BY abcd_pk ;
WORKS IN 10G
DOES NOT WORK IN 12C (ORA-00979: not a GROUP BY expression 00979. 00000 - "not a GROUP BY expression")
Our code may contains case2 like SQL which is not appropriate. So we need to identify those SQLs. I already prepared a list of SQLs contains GROUP BY used in our project (.java files/procedure/function/views etc.).
Requirement is find the problem in GROUP BY using the following process:
Check the SQLs in the list one by one.
Find an alternate way to check the list of SQLs programmatically.
Option 1 requires massive work load, effort and time, but I think option 2 is not possible.
Is there any suggestion how to proceed?
One possible workaround which might work would be to place the count subquery into an aggregate function, e.g. AVG():
SELECT abcd_pk,
COUNT(abcd_code),
AVG(ABCD_COUNT) -- use an aggregate to not offend Oracle
FROM
(
SELECT abcd_pk,
abcd_code,
(SELECT COUNT(abcd_code) FROM ABCD_TABLE) "ABCD_COUNT"
FROM ABCD_TABLE
)
GROUP BY abcd_pk;
If this fixes the problem, then it means that Oracle's treatment of subqueries resulting in constants has changed between 10G and 12C.
I have a query:
SELECT ROW_NUMBER() OVER(ORDER BY LogId) AS RowNum
FROM [Log] l
where RowNum = 1
and I'm getting the following error:
Invalid column name 'RowNum'.
I did some search here and found that column aliasing is not available in WHERE.
so I tried the the following and it worked:
select *
from
(
SELECT ROW_NUMBER() OVER(ORDER BY LogId) AS RowNum
FROM [Log] l
) as t
where t.RowNum = 1
Is there a better way, from performance point of view, to make this query?
Thanks in advance.
That's just the way it is.
Column aliases can not be used on the same logical level where they were defined. You will have to use the derived table (sub-query) as you have found out.
If you are concerned about performance, then don't. The derived table is mere syntactical sugar, it won't make the query slower (compared to the solution you tried first).
An alternative to this specific query, which won't perform any different but is simpler to write:
SELECT TOP 1 <col list> FROM dbo.[Log] ORDER BY LogId;
As #a_horse explained, don't be concerned that because your second query looks like more code that it is more expensive. If you want to measure the efficiency of different queries that get the same results, compare their execution plans, not code complexity.
While using SELECT TOP 5 * FROM SOMETABLE gives me an error
ORA-00923: FROM keyword not found where expected
I am using Oracle 11g . I am aware of using rownum for doing the same thing but just wondering SQL TOP usage is not at all supported in Oracle ? Anything need to do extra to make SQL TOP working in Oracle ??
Oracle does not support TOP. Use ROWNUM
SELECT * FROM your_table
WHERE ROWNUM <= 5
SQLFiddle example
No, Oracle does not support TOP.
As you point out, the best approach is to use rownum. Another option is the analytical function ROW_NUMBER.
The rownum keyword, while it gets you the said no. of records, does so only after applying the order by clause if you have one.
So if the SQL server query is as below, it will give you 10 most recently created records.
Select TOP 10 * from mytable order by created_date desc
But to fit Oracle, when you write this, it gets you the 10 records (that may not be the most recent ones) and arranges them in descending order, which is not what you wanted.
Select * from mytable where rownum < 10 order by created_date desc
So writing with an additional select like this would help:
SELECT * FROM (Select * from mytable order by created_date desc) where rownum < 10
SQL TOP does NOT work for Oracle.