using count and sum in different tables [duplicate] - mysql

How do I go about selecting COUNT(*)s from multiple tables in MySQL?
Such as:
SELECT COUNT(*) AS table1Count FROM table1 WHERE someCondition
JOIN??
SELECT COUNT(*) AS table2Count FROM table2 WHERE someCondition
CROSS JOIN? subqueries?
SELECT COUNT(*) AS table3Count FROM table3 WHERE someCondition
Edit:
The goal is to return this:
+-------------+-------------+-------------+
| table1Count | table2Count | table3Count |
+-------------+-------------+-------------+
| 14 | 27 | 0 |
+-------------+-------------+-------------+

You can do it by using subqueries, one subquery for each tableCount :
SELECT
(SELECT COUNT(*) FROM table1 WHERE someCondition) as table1Count,
(SELECT COUNT(*) FROM table2 WHERE someCondition) as table2Count,
(SELECT COUNT(*) FROM table3 WHERE someCondition) as table3Count

You can do this with subqueries, e.g.:
select (SELECT COUNT(*) FROM table1 WHERE someCondition) as table1Count,
(SELECT COUNT(*) FROM table2 WHERE someCondition) as table2Count

Here is simple approach to get purely the row counts from multiple tables, if there are no conditions on specific tables.
Note:
For InnoDB this count is an approximation. However, for MyISAM the count is accurate.
Quoted from the docs:
The number of rows. Some storage engines, such as MyISAM, store the
exact count. For other storage engines, such as InnoDB, this value is
an approximation, and may vary from the actual value by as much as 40%
to 50%. In such cases, use SELECT COUNT(*) to obtain an accurate
count.
Using the information_schema.tables table you can use:
SELECT
table_name,
table_rows
FROM
information_schema.tables
WHERE
table_name like 'my_table%';
Output:
table_name table_rows
my_table_1 0
my_table_2 15
my_table_3 30

You can use UNION
SELECT COUNT(*) FROM table1 WHERE someCondition
UNION
SELECT COUNT(*) FROM table2 WHERE someCondition
UNION
SELECT COUNT(*) FROM table3 WHERE someCondition

You can do this in this way.
SELECT (select count(*) from table1) + (select count(*) from table2) as total_rows
You can add as many tables as you want.

Try changing to:
SELECT
COUNT(table1.*) as t1,
COUNT(table2.*) as t2,
COUNT(table3.*) as t3
FROM table1
LEFT JOIN tabel2 ON condition
LEFT JOIN tabel3 ON condition

Not directly, but it works...
1.- Create a list of the tables you need to count rows.
2.- Put that list in the first column of a spreadsheet.
3.- In the second column, first row, use this formula:
="SELECT '"&A1&"', (SELECT count(*) FROM "&A1&") UNION"
4.- Fill down the formula.
5.- Copy the second column and paste it to do the query.
6.- Don't forget to remove the last UNION.

Related

why the sql correct and the inner mechanism for run it?

the sql as follows come from mysql document. it is:
SELECT * FROM t1 AS t
WHERE 2 = (SELECT COUNT(*) FROM t1 WHERE t1.id = t.id);
The document say It finds all rows in table t1 containing a value that occurs twice in a given column , and doesnot explain the sql.
t1 and t is the same table, so the
count(*) in subquery == select count(*) from t
, isn't it?
count(*) in subquery == select count(*) from t
is wrong. because in mysql you can't use it like that. so you have to run it like that to get result of same id having two rows.
if you want to get count of same occurrence,
SELECT id, name, count(*) AS all_count FROM t1 GROUP BY id HAVING all_count > 1 ORDER BY all_count DESC
And also you can get values as your query like this as well,
select * from t1 where id in ( select id from t1 group by id having count(*) > 1 )
The query contains a correlated subquery in WHERE clause:
SELECT COUNT(*) FROM t1 WHERE t1.id = t.id
It is called correlated because it is related to the main query via t.id. So, this subquery counts the number of records having an id value that is equal to the current id value of the record returned by the main query.
Thus, predicate
(SELECT COUNT(*) FROM t1 WHERE t1.id = t.id) = 2
evaluates to true for any row with an id value that occurs twice in the table.
SELECT * FROM t1 AS t
WHERE 2 = (SELECT COUNT(*) FROM t1 WHERE t1.id = t.id);
This query goes through each record in t1 and then in the subquery looks into t1 again to see if in this case id is found 2 times (and only 2 times). You can do the same for any other column in t1 (or any table for that matter).
When you would like to see all values that are multiple times in the table, change WHERE 2 = by WHERE 1 <. This will also give you the values that are 3 times, 4 times, etc. in the table.
{
SELECT id,count( * )
FROM
MyTable
group by id
having count( * )>1
}
with this code, you can see the rows which repet more than one,
and you can change this query by yourself
How about using GROUP BY and HAVING:
SELECT id, count(1) as Total FROM MyTable AS t1
GROUP BY t1.id
HAVING Total = 2

Find total records in various tables in a single query

Currently I m using this query ,Is there any substitution for this query,which will work more faster .
SELECT
SUM(result1),
SUM(result2),
SUM(result3)
FROM (
(
SELECT
0 as result1,0 as result2,COUNT(*) as result3
FROM
table1
)
UNION
(
SELECT
count(*) as result1,0 as result2,0 as result3
FROM
table2
)
UNION
(
SELECT
0 as result1,count(*) as result2,0 as result3
FROM
table3
)
) as allresult
Alternate solution of above query is as below:
SELECT (SELECT COUNT(1) FROM table2) AS result1,
(SELECT COUNT(1) FROM table3) AS result2,
(SELECT COUNT(1) FROM table1) AS result3;
Add the table names in the WHERE clause and execute the below query:
SELECT
T.Name AS TableName,
S.Row_count AS RecordsCount
FROM
sys.dm_db_partition_stats S
INNER JOIN sys.tables T ON T.object_id = S.object_id
Where
Object_Name(S.Object_Id) IN ('Employees','Country')
Very simple way to shave some performance load off this query:
Use UNION ALL instead of UNION. UNION ALL will return duplicates if there are any but the only difference between that and waht you are using, just UNION, is that UNION removes these duplicates at the expense of decreased performace. In other words it does a UNION ALL and then goes back and removes the duplicate entries.
It should increase your querys performance
(Copying my comment from this answer)
You can get the row counts for a table from the INFORMATION_SCHEMA as follows (but see caveat below):
SELECT table_rows
FROM information_schema.tables
WHERE table_schema = DATABASE()
AND table_name IN ('table1', 'table2', 'table3');
However the MySQL documentation notes that these values are not exact for InnoDb tables: "For InnoDB tables, the row count is only a rough estimate used in SQL optimization. (This is also true if the InnoDB table is partitioned.)". If you are using MyISAM, this approach may be sufficient.

Wildly different query performance on similar tables?

I am trying to select duplicate rows from a series of MySQL tables. The following query...
SELECT *
FROM table_name
WHERE column_name
IN (SELECT *
FROM (SELECT column_name
FROM table_name
GROUP BY column_name
HAVING COUNT(*) > 1
) AS subquery)
);
...is producing wildly different performance when run in different tables with identical schema and similar number of rows. In one table it executes within a few seconds, in another with identical data types and similar number of rows it is hanging up for an extended period of time (currently at 30 minutes and counting). What possible explanations are there for such a discrepancy?
EDIT - using EXPLAIN is showing that all the queries are returning "Impossible WHERE noticed after reading const tables" for the dependent subquery. This probably is a good time to mention that there are no indexes on any of the tables (which I inherited...). Finding duplicate values in what is supposed to be a uniqid column so that I can turn that into a proper primary key is the point of this entire snape hunt.
I'd suggest splitting the subquery out into a temporary table.
CREATE TEMPORARY TABLE IF NOT EXISTS DupeColumn AS (
SELECT column_name
FROM table_name
GROUP BY column_name
HAVING COUNT(*) > 1
);
SELECT t.*
FROM DupeColumn dc
INNER JOIN table_name t
ON dc.column_name = t.column_name;
DROP TEMPORARY TABLE DupeColumn;
In my experience, MySQL is very poor at optimizing
SELECT *
FROM table1
WHERE col1 in (SELECT col2 FROM table2 WHERE ...)
Instead of performing the subquery once and then looking up all the col2 values in table1, it performs a full scan of table1 and then searches for col1 in table2.col2.
It does better when you write a JOIN:
SELECT table1.*
FROM table1
JOIN table2 ON table1.col1 = table2.col2
In your case, this would be done using a subquery for table2:
SELECT t1.*
FROM table_name AS t1
JOIN (SELECT column_name
FROM table_name
GROUP BY column_name
HAVING COUNT(*) > 1) AS t2
ON t1.column_name = t2.column_name

How to rewrite this SELECT query

I've been left with some code that looks like this:
SELECT DISTINCT ee.* FROM exp_extensions ee WHERE enabled = 'y'
Our db admin is screaming about the select all, and wants us to grab all the individual fields separately. I've never seen a SELECT DISTINCT * before; how would I rewrite that?
Option 1:
SELECT DISTINCT ee.extension_id, ee.class, ee.method, ee.hook, ee.settings, ee.priority, ee.version, ee.enabled FROM exp_extensions ee WHERE enabled = 'y'
Option 2:
SELECT DISTINCT (ee.extension_id, ee.class, ee.method, ee.hook, ee.settings, ee.priority, ee.version, ee.enabled) FROM exp_extensions ee WHERE enabled = 'y'
Or some other way entirely?
There is no difference between Option 1 or Option 2. Say you have a table that has one column col1 that has one row. All of these produce the same result:
SELECT DISTINCT * FROM t1
SELECT DISTINCT col1 FROM t1
SELECT DISTINCT (col1) FROM t1
SELECT * FROM t1
SELECT col1 FROM t1
SELECT (col1) FROM t1
All the * does is essentially expand to all available columns on the table.

Multiple select statements in Single query

I am generating a report in php (mysql),
ex:
`select count(id) as tot_user from user_table
select count(id) as tot_cat from cat_table
select count(id) as tot_course from course_table`
Like this I have 12 tables.
Can i make it in single query. If i did? Process gets slow?
SELECT (
SELECT COUNT(*)
FROM user_table
) AS tot_user,
(
SELECT COUNT(*)
FROM cat_table
) AS tot_cat,
(
SELECT COUNT(*)
FROM course_table
) AS tot_course
If you use MyISAM tables, the fastest way is querying directly the stats:
select table_name, table_rows
from information_schema.tables
where
table_schema='databasename' and
table_name in ('user_table','cat_table','course_table')
If you have InnoDB you have to query with count() as the reported value in information_schema.tables is wrong.
You can certainly us the a Select Agregation statement as Postulated by Ben James, However This will result in a view with as many columns as you have tables. An alternate method may be as follows:
SELECT COUNT(user_table.id) AS TableCount,'user_table' AS TableSource FROM user_table
UNION SELECT COUNT(cat_table.id) AS TableCount,'cat_table' AS TableSource FROM cat_table
UNION SELECT COUNT(course_table.id) AS TableCount, 'course_table' AS TableSource From course_table;
The Nice thing about an approch like this is that you can explicitly write the Union statements and generate a view or create a temp table to hold values that are added consecutively from a Proc cals using variables in place of your table names. I tend to go more with the latter, but it really depends on personal preference and application. If you are sure the tables will never change, you want the data in a single row format, and you will not be adding tables. stick with Ben James' solution. Otherwise I'd advise flexibility, you can always hack a cross tab struc.
select RTRIM(A.FIELD) from SCHEMA.TABLE A where RTRIM(A.FIELD) = ('10544175A')
UNION
select RTRIM(A.FIELD) from SCHEMA.TABLE A where RTRIM(A.FIELD) = ('10328189B')
UNION
select RTRIM(A.FIELD) from SCHEMA.TABLE A where RTRIM(A.FIELD) = ('103498732H')
SELECT t1.credit,
t2.debit
FROM (SELECT Sum(c.total_amount) AS credit
FROM credit c
WHERE c.status = "a") AS t1,
(SELECT Sum(d.total_amount) AS debit
FROM debit d
WHERE d.status = "a") AS t2
I know this is an old stack but i will post this Multi-SQL select case
SELECT bp.bizid, bp.usrid, bp.website,
ROUND((SELECT SUM(rating) FROM ratings WHERE bizid=bp.bizid)/(SELECT COUNT(*) FROM ratings WHERE bizid=bp.bizid), 1) AS 'ratings',
(SELECT COUNT(*) FROM bzreviews WHERE bizid=bp.bizid) AS 'ttlreviews',
bp.phoneno, als.bizname,
(SELECT COUNT(*) FROM endorsment WHERE bizid=bp.bizid) AS 'endorses'
, als.imgname, bp.`location`, bp.`ownership`,
(SELECT COUNT(*) FROM follows WHERE bizid=bp.bizid) AS 'followers',
bp.categories, bp.openhours, bp.bizdecri FROM bizprofile AS bp
INNER JOIN alluser AS als ON bp.usrid=als.userid
WHERE als.usertype='Business'