I have a set of tables in Oracle and I would like to identify the table that contains the maximum number of rows.
So if, A has 200 rows, B has 345 rows and C has 120
David Aldridge correctly points out that querying all_tables could give incorrect results due to missing or stale table statistics. But there is also a problem with using user_segments; Deleted blocks beneath the high water mark would still be counted for the size of the table.
Example:
SQL>create table t as select * from all_objects
Table created.
SQL>select blocks, bytes from user_segments where segment_name = 'T';
BLOCKS BYTES
---------- ----------
768 6291456
SQL>delete from t
52676 rows deleted.
SQL>commit;
Commit complete.
SQL>select count(*) from t;
COUNT(*)
----------
0
SQL>select blocks, bytes from user_segments where segment_name = 'T';
BLOCKS BYTES
---------- ----------
768 6291456
SQL>truncate table t;
Table truncated.
SQL>select blocks, bytes from user_segments where segment_name = 'T';
BLOCKS BYTES
---------- ----------
8 65536
You could get the same result with one trawl of the data like so:
SELECT DISTINCT
FIRST_VALUE ( t.owner )
OVER ( ORDER BY t.num_rows DESC NULLS LAST )
owner,
FIRST_VALUE ( t.table_name )
OVER ( ORDER BY t.num_rows DESC NULLS LAST )
table_name,
FIRST_VALUE ( t.num_rows )
OVER ( ORDER BY t.num_rows DESC NULLS LAST )
num_rows
FROM all_tables t
select max(select count(*) from A union select count(*) from B...)
should work.
edit: if you want something dynamic, you can build a string in PL/SQL with each "count(*)" subquery (for example, listing the table names from USER_TABLES), and then execute te main query with:
execute immediate 'select max('||subquery||')'
Here's another method, likely to be much slower than simply getting ALL_TABLES.NUM_ROWS, but it doesn't depend on statistics having been gathered and gives exact, current values -- although how current depends on how long it takes to run!
-- For running in SQLPlus you need this to see the output.
-- If running in Toad or similar tool, output is enabled by default
SET SERVEROUTPUT ON SIZE 100000
DECLARE
l_rows INTEGER;
l_max_rows INTEGER := 0;
l_table_name all_tables.table_name%TYPE := NULL;
BEGIN
FOR table_record IN (SELECT table_name FROM all_tables) LOOP
EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM '||table_record.table_name
INTO l_rows;
IF l_rows > l_max_rows THEN
l_max_rows := l_rows;
l_table_name := table_record.table_name;
END IF;
END LOOP;
IF l_table_name IS NULL THEN
dbms_output.put_line( 'All tables are empty' );
ELSE
dbms_output.put_line( 'Table ' || table_record.table_name ||
' has ' || TO_CHAR(l_max_rows) || ' rows'
);
END IF;
END;
/
Given that you said you were using Oracle I would just query the meta-data.
select table_name, max(num_rows) from all_tables where table_name in ('A', 'B', 'C');
Just saw your edit. Just run the above without the where clause and it will return the largest table in the database. Only problem may be that you might get a SYS$ table or something. Alternately if you are just doing this for your own knowledge just do
select table_name, num_rows from all_tables order by num_rows;
and you'll see what the biggest are.
This is a query to get the maximum numbers of rows there in a database table..
select table_name, num_rows from USER_TABLES
where num_rows = (select max(num_rows) from
(select table_name, num_rows from USER_TABLES));