Oracle query taking too much of time when I use rownum - oracle

If I execute below query, it is returning results very fast.
(select * from
select * from t1, t2 t3, t4 where ...(inner/outer join) group by ...) order by create_date desc)
How ever If I use ROWNUM like below, it is taking too much of time.
select * from (select * from
select * from t1, t2 t3, t4 where ...(inner/outer join) group by ...) order by create_date desc) where rownum =1
could you please let me know why t is taking too much of time. How I can get latest date record.

Are you see all returning results for first query or are you see first few rows and you don't wait last row?
I think in second query, first works internal query and after the condition "rownum =1" check all result records

Related

Oracle DB query to get records count and calculate average afterward

Could anyone please help me regarding that Oracle query.
Here is my required output.
Thanks in advanced.from below query return some record i want to Calculate
Average means SUM(COST+DURATION)/No.of row return form that query but below query doing partition based on SITE_ID i dont want any partition,What is want is whatever query return (Sum of all Duration+sum of all Cost/No. of row returns)but without any partition is that any way i can do that
select * from (
SELECT ROW_NUMBER() OVER (ORDER BY 1) RN,
SITE_ID,
CASEID,
WOID,
DURATION,
COST,
(SUM(COST+DURATION) OVER(PARTITION BY SITE_ID))/COUNT as TotalCost from
(
SELECT COUNT(*) OVER () as COUNT,
SITE_ID,
CASEID,
WOID,
ROUND(table1.duration/3600,2) AS DURATION,
ROUND(table2.duration/3600),2) AS COST
FROM table1 ) AVG
WHERE (1=1)
)
where rn between 0 and 1000
On the basis of your revised question what I think you want is the total of COST and DURATION for each SITE, plus an average of these figures derived from the number of entries in table1 and table2. This is what this query does:
select site_id
, duration
, cost
, (duration+cost)/no_of as avg_total_cost
from (
select
table1.site_id
, count(*) as no_of
, sum(round(table1.duration/3600,2)) as duration
, sum(round((table1.labor_rate * table2.duration)/3600,2)) as cost
from table1
inner join table2
on table1.id = table2.id
group by table1.site_id
)
/
Here is a SQL Fiddle demo to prove that this query runs successfully.
Your question appears to reference other tables, site and emp, which I have ignored because you don't provide join conditions for them. Likewise I have ignored the top-n filter; you can add it back it if you want.

select * from (select first_name, last_name from employees)

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.

Oracle: Returning the earliest date

I have a stored procedure which I use to return the earliest available date in a column of dates. I need to only return the earliest, and currently am using date arithmetic to reduce the number of returned rows. However, doing it this way, my procedure gets stuck in a loop of the first two top returned values, meaning I have several rows which are never read. Could somebody please let me know where I need to use the MIN function in the following WHERE clause, please? Thanks:
SELECT **COLS**
INTO **VARS**
FROM **TABLE**
INNER JOIN **TABLE TO JOIN**
ON **JOIN TARGET**
WHERE ROWNUM = 1 AND LASTREADTIME < SYSDATE - (30/86400)
ORDER BY LASTREADTIME DESC;
if you only need the earliest date
SELECT MIN(LastReadTime)
INTO **VARS**
FROM table
if you need other datas
SELECT t2.col1, t1.col1, t1.col2, t1.LastTreadTime
INTO **VARS**
FROM table t1
JOIN table2 t2 on t1.col1 = t2.col1
WHERE t1.LastReadTime = (SELECT MIN(t2.LastReadTime) FROM table t2);

Sybase expert help: groupby aggregate performance problems

Hey I have the following tables and SQL:
T1: ID, col2,col3 - PK(ID) - 23mil rows
T2: ID, col2,col3 - PK(ID) - 23mil rows
T3: ID, name,value - PK(ID,name) -66mil rows
1) The below sql returns back the 10k row resultset very fast, no problems.
select top 10000 T1.col2, T2.col2, T3.name, T4.value
from T1, T2, T3
where T1.ID = T2.ID and T1.ID *= T3.ID and T3.name in ('ABC','XYZ')
and T2.col1 = 'SOMEVALUE'
2) The below sql took FOREVER.
select top 10000 T1.col2, T2.col2,
ABC = min(case when T3.name='ABC ' then T3.value end)
XYZ = min(case when T3.name='XYZ ' then T3.value end)
from T1, T2, T3
where T1.ID = T2.ID and T1.ID *= T3.ID and T3.name in ('ABC','XYZ')
and T2.col1 = 'SOMEVALUE'
group by T1.col2, T2.col2,
The only difference in the showplan between those 2 queries are the below for query 2). I dont understand it 100%, is it selecting the ENTIRE resultset WITHOUT top 10000 into the temp table then doing a group by on it? is that why it's slow?
STEP 1
The type of query is SELECT (into Worktable1).
GROUP BY
Evaluate Grouped MINIMUM AGGREGATE.
FROM TABLE ...etc..
TO TABLE
Worktable1.
STEP 2
The type of query is SELECT.
FROM TABLE
Worktable1.
Nested iteration.
Table Scan.
Forward scan.
Positioning at start of table.
Using I/O Size 16 Kbytes for data pages.
With MRU Buffer Replacement Strategy for data pages.
My question is
1) Why is query 2) so slow
2) How do I fix while keeping the query logic the same and preferably limit it to just 1 select SQL as before.
thank you
Although possibly a generic answer, I'd say to put a index on the columns you're grouping by.
Edit / Revise: Here's my theory after re-looking at the issue. The SELECT statement in a query is always the last line executed. This makes sense as it is the statement that retrieves the values you want from the dataset specified below. In your query, the whole dataset (millions of records) will be evaluated for the MIN value expression that you specified. There will be two seperate functions called on the entire dataset, since you have specified two MIN columns in the select statement. After the dataset is filtered and the MIN columns have been determined, the top 10000 rows will then be selected.
In a nutshell, you're doing two mathematical function on millions of records. This will take a significant amount of time, especially with no indexes.
The solution for you would be to use a derived table. I haven't compiled the code below, but it's something close to what you would use. It will only take the min values of the 10,000 records rather than the whole dataset.
I.e.
Select my_derived_table.t1col2, my_derived_table.t2col2,
ABC = min(case when my_derived_table.t3name ='ABC ' then my_derived_table.t3value end),
XYZ = min(case when my_derived_table.t3name='XYZ ' then my_derived_table.t3value end)
FROM
(Select top 10000 T1.col2 as t1col2,
T2.col2 as t2col2,
t3.name as t3name,
t3.value as t3.value
from T1, T2, T3
where T1.ID = T2.ID
and T1.ID *= T3.ID
and T3.name in ('ABC','XYZ')
and T2.col1 = 'SOMEVALUE') my_derived_table
group by my_derived_table.t1col2, my_derived_table.t2col2

Oracle ROWNUM pseudocolumn

I have a complex query with group by and order by clause and I need a sorted row number (1...2...(n-1)...n) returned with every row. Using a ROWNUM (value is assigned to a row after it passes the predicate phase of the query but before the query does any sorting or aggregation) gives me a non-sorted list (4...567...123...45...). I cannot use application for counting and assigning numbers to each row.
Is there a reason that you can't just do
SELECT rownum, a.*
FROM (<<your complex query including GROUP BY and ORDER BY>>) a
You could do it as a subquery, so have:
select q.*, rownum from (select... group by etc..) q
That would probably work... don't know if there is anything better than that.
Can you use an in-line query? ie
SELECT cols, ROWNUM
FROM (your query)
Assuming that you're query is already ordered in the manner you desire and you just want a number to indicate what row in the order it is:
SELECT ROWNUM AS RowOrderNumber, Col1, Col2,Col3...
FROM (
[Your Original Query Here]
)
and replace "Colx" with the names of the columns in your query.
I also sometimes do something like:
SELECT * FROM
(SELECT X,Y FROM MY_TABLE WHERE Z=16 ORDER BY MY_DATE DESC)
WHERE ROWNUM=1
If you want to use ROWNUM to do anything more than limit the total number of rows returned in a query (e.g. AND ROWNUM < 10) you'll need to alias ROWNUM:
select *
(select rownum rn, a.* from
(<sorted query>) a))
where rn between 500 and 1000

Resources