Select and count the same records - oracle

In my Stored Procedure, I have two queries:
Here rec_count is out parameter and cursor_name is in out parameter.
open cursor_name for
select <col list> from <table1 join table2 inner join...> on <join conditions> where <conditions>;
select count(*) into rec_count from <table1 join table2 inner join...> on <join conditions> where <conditions>;
Is there a way I can do the select and count together as I am providing the same join conditions and where clause again?
Will this affect performance or SQL Optimizer will optimize these two queries?

You could do the analytic count over the entire data set like this -
OPEN cursor_name for
SELECT <col_list> ,
count(*) over () as cnt
from <tables> <join conditions> <where clauses>;
That way the cursor would have a column with the count of all rows in each row.

There are bigger issues than you are thinking to be here.
What if another session commits a transaction meanwhile between you open the cursor and select count? Obviously, the count of the rows that of the cursor will not match with your select count(*) query.
Oracle doesn't know the count of rows, until the last row is fetched.
If you want an exact count of rows, then I would insist an analytic count(*) over() in your existing cursor query.

Related

Convert rownum from Oracle in Postgres, in "having" clause

I need to convert a query from Oracle SQL to Postgres.
select count(*) from table1 group by column1 having max(rownum) = 4
If I replace "rownum" with "row_number() over()", I have an error message: "window functions are not allowed in HAVING".
Could you help me to get the same result in Postgres, as in Oracle?
The query below will do what your Oracle query is doing.
select count(*) from
(select column1, row_number() over () as x from table1) as t
group by column1 having max(t.x) = 6;
However
Neither oracle not postgres will guarantee the order in which records are read unless you specify an order by clause. So running the query multiple times is going to be inconsistent depending on how the database decides to process the query. Certainly in postgres any updates will change the underlying row order.
In the example below I've got an extra column of seq which is used to provide a consistent sort.
CREATE TABLE table1 (column1 int, seq int);
insert into table1 values (0,1),(0,2),(0,3),(1,4),(0,5),(1,6);
And a revised query which forces the order to be consistent:
select count(*) from
(select column1, row_number() over (order by seq) as x from table1) as t
group by column1 having max(t.x) = 6;

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.

How can I display the all the table names, along with their count of column names?

My database has a lot of tables. How can I display all the table names along with the count of column names in each table?
myoutput:
------------
table_name count(*)
---------- --------
table_t1 12
x_a 5
Y_k 23
samptabl 0
Use USER_TAB_COLS view to get the column_count.
SELECT table_name, count(*) column_count
FROM user_tab_cols
GROUP BY table_name;
If you want the name of the table with the number of columns in it, use DBA's answer here.
If you want name of the table and the number of rows in it, use the following:
SELECT table_name, num_rows
FROM user_tables;
The numbers of rows in this query represent the numbers when the table was last analyzed. To return the latest numbers run ANALYSE tablename before running this query.
If you want to know all table_names and columns count in your Entire Database then here is the query.
Query : SELECT TABLE_NAME,COUNT(COLUMN_NAME) as No_Of_Cols
FROM ALL_TAB_COLS
GROUP BY TABLE_NAME;
Thanks,
Venu.
SELECT table_name, count(*) column_count
FROM all_tables
GROUP BY table_name;

Counting rows by a condition in another table

Need to count the number of rows in one table which connect to a second table by (name.sample) where in the second table the (name.sample) was created before (or after) a certain date.
select count(*) from table1 t1
inner join table2 t2 on t1.my_foreign_key_column = t2.my_primary_key_column
where t2.creation_date >= 'my_date_literal'

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