0

I have been trying to do it but not able to do it with list_agg

I have 1 table which as all table names in it

Table name : get_tables

Below are all table names in get_tables. get tables as column called tbl_names

tbl_names -------------- EMP_1 EMP_2 STUD_1 STUD_2 DEMO_1 STUDENT_DETAILS 

I have written a consolidated one query to get all tables count

select 'SELECT ' || '''' || tbl_names || '''' || ' AS TBL , COUNT(*) as CNT FROM from tbl_names || 'union' from get_tables; 

Basically I am generating below query as an output from above query

 0 SELECT 'EMP_1' AS TBL , COUNT(*) from EMP_1 union 1 SELECT 'EMP_2' AS TBL , COUNT(*) from EMP_2 union 2 SELECT 'STUD_1' AS TBL , COUNT(*) from STUD_1 union 3 SELECT 'STUD_2' AS TBL , COUNT(*) from STUD_1 union 4 SELECT 'DEMO_1' AS TBL , COUNT(*) from DEMO_1 union 5 SELECT 'STUDENT_DETAILS' AS TBL , COUNT(*) from STUDENT_DETAILS union 

Now 2 things I want first is above query are records
need to combine all as one query and remove last keyword union from last line and replace with ';'

So that this generated query I can run it in one go from my python script to get all table count with table name

Expected output :

TABLE COUNT EMP_1 10 EMP_2 20 STUD_1 40 STUD_2 50 DEMO_1 50 STUDENT_DETAILS 100 
7
  • What happened when you used listagg? Share your attempt at any errors Commented May 1, 2022 at 14:30
  • @AndrewSayer Not able to frame query with list_agg Commented May 1, 2022 at 14:31
  • 1
    The name of the function is LISTAGG, not LIST_AGG. Commented May 1, 2022 at 14:43
  • @BobJarvis-СлаваУкраїні ... its typo error in my question i tried that LISTAGG Commented May 1, 2022 at 14:46
  • Are you certain LISTAGG will work (meaning, the result will always be less than 4000 characters)? Commented May 1, 2022 at 14:48

2 Answers 2

2

Here's one way, using LISTAGG to illustrate the method. If you have too many tables, you will need a different way of aggregating (such as XMLAGG), but that's a different issue - you can find hundreds of questions about that here on SO.

Best to use UNION ALL rather than UNION, but if you insist on just UNION, you can modify the solution yourself. Use LISTAGG, but don't include UNION [ALL] in the tokens to be aggregated; rather, use it as the delimiter!

For easier reading of the output, I included a newline in the delimiter as well; that's not needed except for debugging. You may choose to remove it after you are satisfied that the query works as expected.

Also, I didn't bother to concatenate a semicolon at the end; you can add that yourself.

NOTE - the output is a single row, meaning a single string that contains newline characters (and therefore appears as multiple lines of text). It's NOT spread over multiple rows, it's just several lines in a single string in a single row.

EDIT Looking at it again, I see that your individual SELECT statements are incorrect (they show the keyword "from" twice, and all SELECT statements are counting the rows in the get_tables table instead of in each respective table, and perhaps other mistakes as well). I will let you fix all those mistakes; they are unrelated to the main topic of your question, which was about aggregating the statements - whether correct or otherwise - in the desired way.

END EDIT (FURTHER EDIT AT THE BOTTOM OF THE ANSWER)

with get_tables (tbl_names) as ( select 'EMP_1' from dual union all select 'EMP_2' from dual union all select 'STUD_1' from dual union all select 'STUD_2' from dual union all select 'STUD_3' from dual union all select 'STUDENT_DETAILS' from dual ) -- end of sample data, for testing only; remove WITH clause -- and use your actual table and column names. select listagg('SELECT ' || '''' || tbl_names || '''' || ' AS TBL , COUNT(*) as CNT FROM from tbl_names', ' union all' || chr(10)) within group (order by tbl_names) as sql_str from get_tables; SQL_STR ---------------------------------------------------------------------------------- SELECT 'EMP_1' AS TBL , COUNT(*) as CNT FROM from tbl_names union all SELECT 'EMP_2' AS TBL , COUNT(*) as CNT FROM from tbl_names union all SELECT 'STUDENT_DETAILS' AS TBL , COUNT(*) as CNT FROM from tbl_names union all SELECT 'STUD_1' AS TBL , COUNT(*) as CNT FROM from tbl_names union all SELECT 'STUD_2' AS TBL , COUNT(*) as CNT FROM from tbl_names union all SELECT 'STUD_3' AS TBL , COUNT(*) as CNT FROM from tbl_names 

SECOND EDIT

The OP's use case requires the generation of a CLOB, so LISTAGG won't work. Here's how the query can be modified to work for CLOB output. I corrected the statement at the same time - see my first EDIT, before the first code block.

To make sure this works correctly, I wrote it for the ALL_TABLES view in my schema; the table names are in a column called TABLE_NAME. The OP should change these names for his use case.

select regexp_replace( xmlcast(xmlagg(xmlelement(e, 'select ''' || table_name || ''' as tbl, count(*) as cnt from ' || table_name, ' union all ' || chr(10))) as clob), ' union all ' || chr(10) ||'$', ';') as sql_string from all_tables; 

END SECOND EDIT

Sign up to request clarification or add additional context in comments.

3 Comments

If you are doing counts on tables with many rows you may want to consider adding a parallel hint to help speed these up
@mathguy Your code work for me but does not work for large number of tables like i have 60 tables its not working ... throwing error : make sure the result is less than the maximum size
@cafopa2172 - OK, I will add to my answer, showing how to use XMLAGG for your use case.
1

Why not just query the all_tables table (or user_tables or dba_tables) which holds the row count for each table already?

SELECT TABLE_NAME, NUM_ROWS FROM ALL_TABLES; 

2 Comments

Only partially works few of the tables in different schema so consolidated all as one query to run in that db via scripting
I prefer this solution, but before that he must gather statistics on tables, so num_rows get updated!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.