Count total amount of references from multiple foreign tables in MySQL

SBNTT :

I have 3 tables:

A

B which has a foreign key to A

C same

How can I count the total number of relations that references a row in A?

ex.


A

+----+------+
| id | name |
+----+------+
|  1 |  foo |
|  2 |  bar |
+----+------+

B

+----+----+
| id |  a |
+----+----+
|  1 |  1 |
|  2 |  1 |
|  3 |  2 |
|  4 |  2 |
+----+----+

C

+----+----+
| id |  a |
+----+----+
|  1 |  1 |
|  2 |  1 |
+----+----+

I want to get this result:

+------+----+
| name |  a |
+------+----+
| foo  |  4 |
| bar  |  2 |
+------+----+

Thanks

Patrick Allaert :

Edit 1: taking into account that all children tables may be empty

Edit 2: Accepted answer is inefficient and will result in temporary table being created by the union of the size of B + C, then grouping will be performed on that temporary table. An explain plan on that query reveals Using temporary; Using filesort, both being bad:

+------+-------------+------------+-------+---------------+------+---------+-----------------+------+---------------------------------+
| id   | select_type | table      | type  | possible_keys | key  | key_len | ref             | rows | Extra                           |
+------+-------------+------------+-------+---------------+------+---------+-----------------+------+---------------------------------+
|    1 | PRIMARY     | A          | ALL   | NULL          | NULL | NULL    | NULL            | 5    | Using temporary; Using filesort |
|    1 | PRIMARY     | <derived2> | ref   | key0          | key0 | 5       | A.id            | 2    |                                 |
|    2 | DERIVED     | B          | index | NULL          | a    | 4       | NULL            | 15   | Using index                     |
|    3 | UNION       | C          | index | NULL          | a    | 4       | NULL            | 14   | Using index                     |
+------+-------------+------------+-------+---------------+------+---------+-----------------+------+---------------------------------+

While if you simply sum up the individual COUNT, you would only have the indexes being queried to know the amount of elements:

SELECT name,
  (SELECT COUNT(*) FROM B WHERE B.a = A.id) +
  (SELECT COUNT(*) FROM C WHERE C.a = A.id) AS count
FROM A;

This would result in the following explain plan:

+------+--------------------+-------+------+---------------+------+---------+-----------------+------+-------------+
| id   | select_type        | table | type | possible_keys | key  | key_len | ref             | rows | Extra       |
+------+--------------------+-------+------+---------------+------+---------+-----------------+------+-------------+
|    1 | PRIMARY            | A     | ALL  | NULL          | NULL | NULL    | NULL            | 5    |             |
|    3 | DEPENDENT SUBQUERY | C     | ref  | a             | a    | 4       | A.id            | 1    | Using index |
|    2 | DEPENDENT SUBQUERY | B     | ref  | a             | a    | 4       | A.id            | 1    | Using index |
+------+--------------------+-------+------+---------------+------+---------+-----------------+------+-------------+

Queries and explain plan of accepted answer + this one available in the demo.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=8652&siteId=1