Selecting Sum of the Count From Tables in a DB - sql

I have the following query:
SELECT SUM(count)
FROM (SELECT 'artist' AS table_name, COUNT(*) as count FROM artist
UNION
SELECT 'persons' AS table_name, COUNT(*) as count FROM persons
UNION
SELECT 'track' AS table_name, COUNT(*) as count FROM track)
It works as expected and returns the proper count. But now when I do the following query I get the incorrect count:
SELECT SUM(count)
FROM (SELECT COUNT(*) as count FROM artist
UNION
SELECT COUNT(*) as count FROM persons
UNION
SELECT COUNT(*) as count FROM track)
Why is it the first query gets the proper count and the second one does not?

The UNION eliminates duplicate values, so if two counts happen to be the same, one is eliminated and only one is summed. Try using UNION ALL instead.
SELECT sum(count) FROM
(SELECT COUNT(*) as count FROM artist
UNION ALL
SELECT COUNT(*) as count FROM persons
UNION ALL
SELECT COUNT(*) as count FROM track)

If you can live with approximate, just count all tables in one go
SELECT
Total_Rows= SUM(st.row_count)
FROM
sys.dm_db_partition_stats st
WHERE
(index_id < 2) --cover both heaps and clustered indexes
AND
OBJECT_SCHEMA_NAME (object_id) <> 'sys' --ignore system stuff
This will run in a flash
Adopting your original, you can get count per table and overall in one go..
SELECT
*,
SUM(count) OVER () AS GrandTotal
FROM (SELECT 'artist' AS table_name, COUNT(*) as count FROM artist
UNION
SELECT 'persons' AS table_name, COUNT(*) as count FROM persons
UNION
SELECT 'track' AS table_name, COUNT(*) as count FROM track)

How is it inaccurate? One way might be because, in the second query, you hvae UNION, and two or more rows contain the same value--because UNION removes duplicate values. Try it with UNION ALL, which returns all rows, not just unique ones.

Related

How to retrieve information from table in one statement when the result has different numbers of rows?

I want to retrieve different information in one statement from the same table and they have different number of rows.
The first select has five rows in the result and the second select has three rows because some prices have null value. I thought maybe if I can put zero instead of null so they will match the same number of rows but I don't know how to do that, or is there another solution?
select count(ID), Land
from Film_ha2911
group by Land
union
select count(ID)
from Film_ha2911
where Price is not null
group by Land;
The use of UNION implies that the number and type of columns in select must corresponding
so in your case you should use null for not select columns
select count(ID), Land
from Film_ha2911
group by Land
union
select count(ID), null
from Film_ha2911
where Price is not null
group by Land;
But in this case seems you need a left join on the subquery for land
select t1.count1, t1.land , t2.count2
from (
select count(ID) count1, Land
from Film_ha2911
group by Land
) t1
left join (
select count(ID) count2, land
from Film_ha2911
where Price is not null
group by Land;
) t2 on t1.land = t2.land
The desired result can be achieved by single SELECT without UNION.
Extra column: PriceNotNull to differentiate is Price value filled or not:
SELECT
Land,
CASE WHEN Price IS NOT NULL THEN 'True' ELSE 'False' END PriceNotNull,
COUNT(ID) AS Count_ID
FROM Film_ha2911
GROUP BY Land, CASE WHEN Price IS NOT NULL THEN 'True' ELSE 'False' END
You can just use count():
select Land, count(*) as total_rows,
count(price) as total_with_price
from Film_ha2911
group by Land;
count() counts the number of non-NULL values, so no special logic is needed to count non-NULL values. By count(id) I assume you want to count all the rows. count(*) is more explicit -- as would count(1) which some people prefer.
If you actually want this on separate rows, I would add an indicator for what the count means:
select Land, 'total rows' as which, count(*) as total_rows
from Film_ha2911
group by Land
union all
select Land, 'with price', count(price)
from Film_ha2911
group by Land;
However, I think the first version with two separate columns is more useful.

SQL/HIVE - Distinct count query - How does SELECT COUNT (DISTINCT columns,..) differ from SELECT COUNT(*) with subquery of DISTINCT records

In HIVE, I tried getting the count of distinct rows in 2 methods,
SELECT COUNT (*) FROM (SELECT DISTINCT columns FROM table);
SELECT COUNT (DISTINCT columns) FROM table;
Both are yielding DIFFERENT RESULTS.
The count for the first query is greater than the second query.
How are they working differently?
Thanks in advance.
Do a slight change to your query, ie name your sub query for eg:
SELECT COUNT (*) FROM (SELECT DISTINCT columns FROM table) myquery;
Try with this in hive:
SELECT COUNT (DISTINCT nvl(columns,'NA')) FROM table;
or:
SELECT COUNT (DISTINCT coalesce(columns,'NA')) FROM table;
Above query output will be same as below:
SELECT COUNT (*) FROM (SELECT DISTINCT columns FROM table);

SUM two SELECT COUNT Queries with GROUP BY

I have two queries in a linked database (linking tables from two different project databases). I need to combine the queries to get a total count that is grouped by Interaction_Type1. The SQL code is as follows:
Query#1:
SELECT Sum(Temp.cnt) AS SumOfcnt, Temp.Interaction_Type1
FROM (SELECT COUNT(*) as cnt, Interaction_Type1 from AMERILOCKMasterConversionTable
GROUP BY Interaction_Type1
UNION ALL
SELECT COUNT(*), Interaction_Type2 from AMERILOCKMasterConversionTable
GROUP BY Interaction_Type2
UNION ALL
SELECT COUNT(*), Interaction_Type3 from AMERILOCKMasterConversionTable
GROUP BY Interaction_Type3
) AS Temp
GROUP BY Temp.Interaction_Type1;
and Query#2
SELECT Sum(Temp.cnt) AS SumOfcnt, Temp.Interaction_Type1
FROM (SELECT COUNT(*) as cnt, Interaction_Type1 from MARKETMasterConversionTable
GROUP BY Interaction_Type1
UNION ALL
SELECT COUNT(*), Interaction_Type2 from MARKETMasterConversionTable
GROUP BY Interaction_Type2
UNION ALL
SELECT COUNT(*), Interaction_Type3 from MARKETMasterConversionTable
GROUP BY Interaction_Type3
) AS Temp
GROUP BY Temp.Interaction_Type1;
I would like the query to yeild the following results:
Interaction_Type1 Total
Left_Message 23
Made_Contact 16
Bad_Phone_Number 8
No_Answer 12
I am brand new to SQL and have researched all of this online and have had no luck in combining these two queries to produce the desired results.
Any help would be GREATLY appreciated!!
Thanks!
Red
You should have something like
SELECT Integration_Type, SUM(*)
FROM ( SELECT Integration_Type, SumOfcnt FROM VIEW1
UNION ALL
SELECT Integration_Type, SumOfcnt FROM VIEW2)
GROUP BY Integration_Type
but before create views for queries you have provided here, or just gather all your queries in single view.

select max, min values from two tables

I have two tables. Differ in that an archive is a table and the other holds the current record. These are the tables recording sales in the company. In both we have among other fields: id, name, price of sale. I need to select from both tables, the highest and lowest price for a given name. I tried to do with the query:
select name, max (price_of_sale), min (price_of_sale)
from wapzby
union
select name, max (price_of_sale), min (price_of_sale)
from wpzby
order by name
but such an inquiry draws me two records - one of the current table, one table archival. I want to chose a name for the smallest and the largest price immediately from both tables. How do I get this query?
Here's two options (MSSql compliant)
Note: UNION ALL will combine the sets without eliminating duplicates. That's a much simpler behavior than UNION.
SELECT Name, MAX(Price_Of_Sale) as MaxPrice, MIN(Price_Of_Sale) as MinPrice
FROM
(
SELECT Name, Price_Of_Sale
FROM wapzby
UNION ALL
SELECT Name, Price_Of_Sale
FROM wpzby
) as subQuery
GROUP BY Name
ORDER BY Name
This one figures out the max and min from each table before combining the set - it may be more performant to do it this way.
SELECT Name, MAX(MaxPrice) as MaxPrice, MIN(MinPrice) as MinPrice
FROM
(
SELECT Name, MAX(Price_Of_Sale) as MaxPrice, MIN(Price_Of_Sale) as MinPrice
FROM wapzby
GROUP BY Name
UNION ALL
SELECT Name, MAX(Price_Of_Sale) as MaxPrice, MIN(Price_Of_Sale) as MinPrice
FROM wpzby
GROUP BY Name
) as subQuery
GROUP BY Name
ORDER BY Name
In SQL Server you could use a subquery:
SELECT [name],
MAX([price_of_sale]) AS [MAX price_of_sale],
MIN([price_of_sale]) AS [MIN price_of_sale]
FROM (
SELECT [name],
[price_of_sale]
FROM [dbo].[wapzby]
UNION
SELECT [name],
[price_of_sale]
FROM [dbo].[wpzby]
) u
GROUP BY [name]
ORDER BY [name]
Is this more like what you want?
SELECT
a.name,
MAX (a.price_of_sale),
MIN (a.price_of_sale) ,
b.name,
MAX (b.price_of_sale),
MIN (b.price_of_sale)
FROM
wapzby a,
wpzby b
ORDER BY
a.name
It's untested but should return all your records on one row without the need for a union
SELECT MAX(value) FROM tabl1 UNION SELECT MAX(value) FROM tabl2;
SELECT MIN(value) FROM tabl1 UNION SELECT MIN(value) FROM tabl2;
SELECT (SELECT MAX(value) FROM table1 WHERE trn_type='CSL' and till='TILL01') as summ, (SELECT MAX(value) FROM table2WHERE trn_type='CSL' and till='TILL01') as summ_hist

adding count( ) column on each row

I'm not sure if this is even a good question or not.
I have a complex query with lot's of unions that searches multiple tables for a certain keyword (user input). All tables in which there is searched are related to the table book.
There is paging on the resultset using LIMIT, so there's always a maximum of 10 results that get withdrawn.
I want an extra column in the resultset displaying the total amount of results found however. I do not want to do this using a separate query. Is it possible to add a count() column to the resultset that counts every result found?
the output would look like this:
ID Title Author Count(...)
1 book_1 auth_1 23
2 book_2 auth_2 23
4 book_4 auth_.. 23
...
Thanks!
This won't add the count to each row, but one way to get the total count without running a second query is to run your first query using the SQL_CALC_FOUND_ROWS option and then select FOUND_ROWS(). This is sometimes useful if you want to know how many total results there are so you can calculate the page count.
Example:
select SQL_CALC_FOUND_ROWS ID, Title, Author
from yourtable
limit 0, 10;
SELECT FOUND_ROWS();
From the manual:
http://dev.mysql.com/doc/refman/5.1/en/information-functions.html#function_found-rows
The usual way of counting in a query is to group on the fields that are returned:
select ID, Title, Author, count(*) as Cnt
from ...
group by ID, Title, Author
order by Title
limit 1, 10
The Cnt column will contain the number of records in each group, i.e. for each title.
Regarding second query:
select tbl.id, tbl.title, tbl.author, x.cnt
from tbl
cross join (select count(*) as cnt from tbl) as x
If you will not join to other table(s):
select tbl.id, tbl.title, tbl.author, x.cnt
from tbl, (select count(*) as cnt from tbl) as x
My Solution:
SELECT COUNT(1) over(partition BY text) totalRecordNumber
FROM (SELECT 'a' text, id_consult_req
FROM consult_req cr);
If your problem is simply the speed/cost of doing a second (complex) query I would suggest you simply select the resultset into a hash-table and then count the rows from there while returning, or even more efficiently use the rowcount of the previous resultset, then you do not even have to recount
This will add the total count on each row:
select count(*) over (order by (select 1)) as Cnt,*
from yourtable
Here is your answare:
SELECT *, #cnt count_rows FROM (
SELECT *, (#cnt := #cnt + 1) row_number FROM your_table
CROSS JOIN (SELECT #cnt := 0 AS variable) t
) t;
You simply cannot do this, you'll have to use a second query.