Select count(*) from multiple tables - sql

How can I select count(*) from two different tables (call them tab1 and tab2) having as result:
Count_1 Count_2
123 456
I've tried this:
select count(*) Count_1 from schema.tab1 union all select count(*) Count_2 from schema.tab2
But all I have is:
Count_1
123
456

SELECT (
SELECT COUNT(*)
FROM tab1
) AS count1,
(
SELECT COUNT(*)
FROM tab2
) AS count2
FROM dual

As additional information, to accomplish same thing in SQL Server, you just need to remove the "FROM dual" part of the query.

Just because it's slightly different:
SELECT 'table_1' AS table_name, COUNT(*) FROM table_1
UNION
SELECT 'table_2' AS table_name, COUNT(*) FROM table_2
UNION
SELECT 'table_3' AS table_name, COUNT(*) FROM table_3
It gives the answers transposed (one row per table instead of one column), otherwise I don't think it's much different. I think performance-wise they should be equivalent.

My experience is with SQL Server, but could you do:
select (select count(*) from table1) as count1,
(select count(*) from table2) as count2
In SQL Server I get the result you are after.

Other slightly different methods:
with t1_count as (select count(*) c1 from t1),
t2_count as (select count(*) c2 from t2)
select c1,
c2
from t1_count,
t2_count
/
select c1,
c2
from (select count(*) c1 from t1) t1_count,
(select count(*) c2 from t2) t2_count
/

select
t1.Count_1,t2.Count_2
from
(SELECT count(1) as Count_1 FROM tab1) as t1,
(SELECT count(1) as Count_2 FROM tab2) as t2

A quick stab came up with:
Select (select count(*) from Table1) as Count1, (select count(*) from Table2) as Count2
Note: I tested this in SQL Server, so From Dual is not necessary (hence the discrepancy).

For a bit of completeness - this query will create a query to give you a count of all of the tables for a given owner.
select
DECODE(rownum, 1, '', ' UNION ALL ') ||
'SELECT ''' || table_name || ''' AS TABLE_NAME, COUNT(*) ' ||
' FROM ' || table_name as query_string
from all_tables
where owner = :owner;
The output is something like
SELECT 'TAB1' AS TABLE_NAME, COUNT(*) FROM TAB1
UNION ALL SELECT 'TAB2' AS TABLE_NAME, COUNT(*) FROM TAB2
UNION ALL SELECT 'TAB3' AS TABLE_NAME, COUNT(*) FROM TAB3
UNION ALL SELECT 'TAB4' AS TABLE_NAME, COUNT(*) FROM TAB4
Which you can then run to get your counts. It's just a handy script to have around sometimes.

As I can't see any other answer bring this up.
If you don't like sub-queries and have primary keys in each table you can do this:
select count(distinct tab1.id) as count_t1,
count(distinct tab2.id) as count_t2
from tab1, tab2
But performance wise I believe that Quassnoi's solution is better, and the one I would use.

SELECT (SELECT COUNT(*) FROM table1) + (SELECT COUNT(*) FROM table2) FROM dual;

Here is from me to share
Option 1 - counting from same domain from different table
select distinct(select count(*) from domain1.table1) "count1", (select count(*) from domain1.table2) "count2"
from domain1.table1, domain1.table2;
Option 2 - counting from different domain for same table
select distinct(select count(*) from domain1.table1) "count1", (select count(*) from domain2.table1) "count2"
from domain1.table1, domain2.table1;
Option 3 - counting from different domain for same table with "union all" to have rows of count
select 'domain 1'"domain", count(*)
from domain1.table1
union all
select 'domain 2', count(*)
from domain2.table1;
Enjoy the SQL, I always do :)

select (select count(*) from tab1) count_1, (select count(*) from tab2) count_2 from dual;

--============= FIRST WAY (Shows as Multiple Row) ===============
SELECT 'tblProducts' [TableName], COUNT(P.Id) [RowCount] FROM tblProducts P
UNION ALL
SELECT 'tblProductSales' [TableName], COUNT(S.Id) [RowCount] FROM tblProductSales S
--============== SECOND WAY (Shows in a Single Row) =============
SELECT
(SELECT COUNT(Id) FROM tblProducts) AS ProductCount,
(SELECT COUNT(Id) FROM tblProductSales) AS SalesCount

If the tables (or at least a key column) are of the same type just make the union first and then count.
select count(*)
from (select tab1key as key from schema.tab1
union all
select tab2key as key from schema.tab2
)
Or take your satement and put another sum() around it.
select sum(amount) from
(
select count(*) amount from schema.tab1 union all select count(*) amount from schema.tab2
)

Declare #all int
SET #all = (select COUNT(*) from tab1) + (select count(*) from tab2)
Print #all
or
SELECT (select COUNT(*) from tab1) + (select count(*) from tab2)

JOIN with different tables
SELECT COUNT(*) FROM (
SELECT DISTINCT table_a.ID FROM table_a JOIN table_c ON table_a.ID = table_c.ID );

SELECT (
SELECT COUNT(*)
FROM tbl1
)
+
(
SELECT COUNT(*)
FROM tbl2
)
as TotalCount

If you're using Google BigQuery this will work.
SELECT
date,
SUM(Table_1_Id_Count) AS Table_1_Id_Count,
SUM(Table_2_Id_Count) AS Table_2_Id_Count
FROM
(
SELECT
Id AS Table_1_Id,
date,
COUNT(Id) AS Table_1_Id_Count,
0 AS Table_2_Id_Count
FROM
`your_project_name.Table_1`
GROUP BY
Id,
date
UNION ALL
SELECT
Id AS Table_2_Id,
date,
0 AS Table_1_Id_Count,
COUNT(Id) AS Table_2_Id_Count
FROM
`your_project_name.Table_2`
GROUP BY
Id,
date
)
GROUP BY
date

select
(select count() from tab1 where field like 'value') +
(select count() from tab2 where field like 'value')
count

select #count = sum(data) from
(
select count(*) as data from #tempregion
union
select count(*) as data from #tempmetro
union
select count(*) as data from #tempcity
union
select count(*) as data from #tempzips
) a

Related

sql sum of sums of two tables

how to get a sum of two sums from two tables?
SELECT (SELECT SUM(col) FROM table1) + SELECT (SUM(col) from table2)
doesn't work
You are very close. You just need parens around each subquery:
SELECT (SELECT SUM(col) FROM table1) + (SELECT SUM(col) from table2)
If either subquery could return NULL, you might prefer:
SELECT COALESCE(t1.s, 0) + COALESCE(t2.s)
FROM (SELECT SUM(col) as s FROM table1) t1 CROSS JOIN
(SELECT SUM(col) as s from table2) t2;
Due to this link, you can do that by :
SELECT T1C1 , T2C1
FROM
( select SUM(Col1) T1C1 FROM T1 ) A
CROSS JOIN
( select SUM(Col1) T2C1 FROM T2 ) B
also you can visit these links:
Query SUM for two fields in two different tables
Getting the sum of several columns from two tables
SQL: How to to SUM two values from different tables
select coalesce(sum(x),0) from
(
Select sum(a) x from tab1
Union all
Select sum(b) from tab2
) Ilv

How to sum rowcounts

How would I count the number of rows in three tables and return the sum of the three row counts?
This will return every table count on your db just add the WHERE to filter the ones you want
http://www.dba-oracle.com/t_count_rows_all_tables_in_schema.htm
select
table_name,
to_number(
extractvalue(
xmltype(
dbms_xmlgen.getxml('select count(*) c from '||table_name))
,'/ROWSET/ROW/C')) row_count
from
user_tables
order by
table_name;
Just include this in a CTE to get the SUM
WITH cte AS (
select
table_name,
to_number(
extractvalue(
xmltype(
dbms_xmlgen.getxml('select count(*) c from '||table_name))
,'/ROWSET/ROW/C')) row_count
from
user_tables
WHERE table_name in ('table1', 'table2', 'table3' )
)
SELECT SUM(row_count)
FROM cte
select sum(rowcount) from
(
select count(*) as rowcount from tablea a
UNION
select count(*) from tableb b
UNION
select count(*) from tablec c
)
Since the number of rows of a table is returned as a single row result, you could cross the join the three results and sum them with the + operator:
SELECT a.cnt + b.cnt + c.cnt
FROM (SELECT COUNT(*) AS cnt FROM table_a) a
CROSS JOIN (SELECT COUNT(*) AS cnt FROM table_b) b
CROSS JOIN (SELECT COUNT(*) AS cnt FROM table_c) c
select sum(v.cnt) as total_sum
from
(select count (*) as cnt from <<table1>>
union all
select count (*) as cnt from <<table2>>
union all
select count (*) as cnt from <<table3>>) v
select
cnt1 + cnt2 + cnt3
as mycnt
from
(SELECT COUNT (*) as cnt1 FROM s1.t1),
(SELECT COUNT (*) as cnt2 FROM s1.t2),
(SELECT COUNT (*) as cnt3 FROM s1.t3)
Is what I ended up using. Thanks all.

How to use union if i need to "order by" all selects

i have 3 separate select statements that i need to union. but all of them need to be ordered by a different column.
i tried doing this
select * from(
select * from (select columns from table1 order by column1 ) A
UNION
select * from (select columns from table2 order by column2 ) B
UNION
select * from (select columns from table3 order by column3 ) C
) Table
but this doesn't work
does anyone have any experience with this?
You can do something like this:
select *
from((select columns, 'table1' as which from table1 )
UNION ALL
(select columns, 'table2' from table2 )
UNION ALL
(select columns, 'table3' from table3 )
) t
order by which,
(case when which = 'table1' then column1
when which = 'table2' then column2
when which = 'table3' then column3
end);
This assumes that the columns used for ordering are all of the same type.
Note that this query uses union all instead of union. I see no reason why you would want to eliminate duplicates if you want the results from the three subqueries ordered independently.
EDIT:
You can also express the order by separately for each table:
order by which,
(case when which = 'table1' then column1 end) ASC,
(case when which = 'table2' then column2 end) DESC
(case when which = 'table3' then column3 end)
You should separate these columns in the one common column and then order
SELECT * FROM
(
SELECT A.*,columnA as ORDER_COL FROM A
UNION ALL
SELECT B.*,columnB as ORDER_COL FROM B
UNION ALL
SELECT C.*,columnC as ORDER_COL FROM C
) as T1
ORDER BY ORDER_COL
You have to order it AFTER the UNION's.
You can "trick it" like this:
select Artificial, a,b,c from(
select 1 as Artificial, a,b,c from (select columns from table1 ) A
UNION
select 2 as Artificial,a,b,c from (select columns from table2 ) B
UNION
select 3 as Artificial,a,b,c from (select columns from table3 ) C
) derivedTable
order by Artificial, c,b,a

On SQL request by column

I have different simple SQL request that return only one value. Example
SELECT COUNT(*) FROM Person
OR
SELECT COUNT(*) FROM Category
I would to get all these infos in a unique request, with a column by request...
I tried something like that but it doesn't work :
SELECT COUNT(C.CategoryId) As nbPeople, COUNT(P.PersonID) As nbCategories FROM Category C, Person P
This works but I get only one column, and a row by request
SELECT COUNT(*) FROM Person UNION SELECT COUNT(*) FROM Category
How Can I simply do that ?
Thanks
When using SQL Server, you can try this:
SELECT ( select COUNT(C.CategoryId)
from Category C
) As nbPeople
, ( select COUNT(P.PersonID)
from Person P
) As nbCategories
In Oracle for example, you need to add this at the bottom
FROM dual
You can use UNION ALL like following:
SELECT '' AS [StatisticName], 1 AS [StatisticCount]
WHERE 1=0
UNION ALL
SELECT 'PersonCount', COUNT(*) FROM [Person]
UNION ALL
SELECT 'CathegoryCount', COUNT(*) FROM [Category]
First select with WHERE 1=0 is for create column header names only and is not necessary.
Try this.
select * from
(select count(*) cnt1
from Table1) t1
join
(select count(*) as cnt2
from Table2) t2 on 1=1

How to use order by with union all in sql?

I tried the sql query given below:
SELECT * FROM (SELECT *
FROM TABLE_A ORDER BY COLUMN_1)DUMMY_TABLE
UNION ALL
SELECT * FROM TABLE_B
It results in the following error:
The ORDER BY clause is invalid in views, inline functions, derived
tables, subqueries, and common table expressions, unless TOP or FOR
XML is also specified.
I need to use order by in union all. How do I accomplish this?
SELECT *
FROM
(
SELECT * FROM TABLE_A
UNION ALL
SELECT * FROM TABLE_B
) dum
-- ORDER BY .....
but if you want to have all records from Table_A on the top of the result list, the you can add user define value which you can use for ordering,
SELECT *
FROM
(
SELECT *, 1 sortby FROM TABLE_A
UNION ALL
SELECT *, 2 sortby FROM TABLE_B
) dum
ORDER BY sortby
You don't really need to have parenthesis. You can sort directly:
SELECT *, 1 AS RN FROM TABLE_A
UNION ALL
SELECT *, 2 AS RN FROM TABLE_B
ORDER BY RN, COLUMN_1
Not an OP direct response, but I thought I would jimmy in here responding to the the OP's ERROR messsage, which may point you in another direction entirely!
All these answers are referring to an overall ORDER BY once the record set has been retrieved and you sort the lot.
What if you want to ORDER BY each portion of the UNION independantly, and still have them "joined" in the same SELECT?
SELECT pass1.* FROM
(SELECT TOP 1000 tblA.ID, tblA.CustomerName
FROM TABLE_A AS tblA ORDER BY 2) AS pass1
UNION ALL
SELECT pass2.* FROM
(SELECT TOP 1000 tblB.ID, tblB.CustomerName
FROM TABLE_B AS tblB ORDER BY 2) AS pass2
Note the TOP 1000 is an arbitary number. Use a big enough number to capture all of the data you require.
There will be times when you need to do something like this :
Pull top 5 from table 1 based on a sort
and bottom 5 from table 2 based on another sort
and union these together.
solution
select * from (
-- top 5 records
select top 5 col1, col2, col3
from table1
group by col1, col2
order by col3 desc ) z
union all
select * from (
-- bottom 5 records
select top 5 col1, col2, col3
from table2
group by col1, col2
order by col3 ) z
this was the only way i was able to get around the error and worked fine for me.
SELECT * FROM (SELECT *
FROM TABLE_A ORDER BY COLUMN_1)DUMMY_TABLE
UNION ALL
SELECT * FROM TABLE_B
ORDER BY 2;
2 is column number here .. In Oracle SQL you can use the column number by which you want to sort the data
This solved my SELECT statement:
SELECT * FROM
(SELECT id,name FROM TABLE_A
UNION ALL
SELECT id,name FROM TABLE_B ) dum
order by dum.id , dum.name
where id and name columns available in tables and you can use your columns .
Simply use that , no need parenthesis or anything else
SELECT *, id as TABLE_A_ID FROM TABLE_A
UNION ALL
SELECT *, id as TABLE_B_ID FROM TABLE_B
ORDER BY TABLE_A_ID, TABLE_B_ID
ORDER BY after the last UNION should apply to both datasets joined by union.
The solution shown below:
SELECT *,id AS sameColumn1 FROM Locations
UNION ALL
SELECT *,id AS sameColumn2 FROM Cities
ORDER BY sameColumn1,sameColumn2
select CONCAT(Name, '(',substr(occupation, 1, 1), ')') AS f1
from OCCUPATIONS
union
select temp.str AS f1 from
(select count(occupation) AS counts, occupation, concat('There are a total of ' ,count(occupation) ,' ', lower(occupation),'s.') As str from OCCUPATIONS group by occupation order by counts ASC, occupation ASC
) As temp
order by f1